@dolaned/wallet-sdk-ts
Version:
Wallet SDK for the Nexa blockchain
259 lines (209 loc) • 9.98 kB
text/typescript
import { describe, test, expect, beforeEach, vi } from 'vitest'
import { TransactionBuilder, Networks } from 'libnexa-ts'
import WatchOnlyTransactionCreator from '../../../src/wallet/transactions/WatchOnlyTransactionCreator'
import { WatchOnlyAddress } from '../../../src/models/wallet.entities'
// Mock the WatchOnlyTXUtils functions
vi.mock('../../../src/utils/WatchOnlyTXUtils', () => ({
watchOnlyPopulateTokenAuth: vi.fn().mockResolvedValue(['address1']),
watchOnlyBuildCreateGroupTransaction: vi.fn().mockResolvedValue(['address2']),
watchOnlyPopulateAndDuplicateTokenAuths: vi.fn().mockResolvedValue(['address3']),
watchOnlyPrepareDeleteTransaction: vi.fn().mockResolvedValue(['address4']),
watchOnlyPopulateTokenInputsAndChange: vi.fn().mockResolvedValue(['address5']),
watchOnlyPopulateNexaInputsAndChange: vi.fn().mockResolvedValue(['address6'])
}))
describe('WatchOnlyTransactionCreator', () => {
let creator: WatchOnlyTransactionCreator
let mockAddresses: WatchOnlyAddress[]
beforeEach(() => {
mockAddresses = [
{ address: 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc' },
{ address: 'nexatest:nqtsq5g5dsgh6mwjchqypn8hvdrjue0xpmz293fl7rm926xv' }
]
creator = new WatchOnlyTransactionCreator()
})
describe('constructor', () => {
test('should create instance without transaction builder', () => {
const creator = new WatchOnlyTransactionCreator()
expect(creator).toBeInstanceOf(WatchOnlyTransactionCreator)
})
test('should create instance with transaction builder', () => {
const txBuilder = new TransactionBuilder()
const creator = new WatchOnlyTransactionCreator(txBuilder)
expect(creator).toBeInstanceOf(WatchOnlyTransactionCreator)
})
})
describe('parseTxBuffer', () => {
test('should not throw error and return this for chaining', () => {
const buffer = Buffer.from('test')
const result = creator.parseTxBuffer(buffer)
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(1)
})
})
describe('parseTxHex', () => {
test('should not throw error and return this for chaining', () => {
const hex = 'deadbeef'
const result = creator.parseTxHex(hex)
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(1)
})
})
describe('from', () => {
test('should accept single address string', () => {
const address = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const result = creator.onNetwork('testnet').from(address)
expect(result).toBe(creator) // Should return this for chaining
expect(creator['_availableAddresses']).toHaveLength(1)
expect(creator['_availableAddresses'][0].address).toBe(address)
})
test('should accept array of address strings', () => {
const addresses = [
'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc',
'nexatest:nqtsq5g5dsgh6mwjchqypn8hvdrjue0xpmz293fl7rm926xv'
]
const result = creator.onNetwork('testnet').from(addresses)
expect(result).toBe(creator)
expect(creator['_availableAddresses']).toHaveLength(2)
expect(creator['_availableAddresses'][0].address).toBe(addresses[0])
expect(creator['_availableAddresses'][1].address).toBe(addresses[1])
})
test('should accept array of WatchOnlyAddress objects', () => {
const result = creator.from(mockAddresses)
expect(result).toBe(creator)
expect(creator['_availableAddresses']).toHaveLength(2)
expect(creator['_availableAddresses'][0]).toEqual(mockAddresses[0])
expect(creator['_availableAddresses'][1]).toEqual(mockAddresses[1])
})
test('should accept single WatchOnlyAddress object', () => {
const address = mockAddresses[0]
const result = creator.from(address)
expect(result).toBe(creator)
expect(creator['_availableAddresses']).toHaveLength(1)
expect(creator['_availableAddresses'][0]).toEqual(address)
})
})
describe('mint', () => {
test('should add mint operation to builder', () => {
const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const amount = '1000'
const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const result = creator.mint(token, amount, toAddr)
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(1)
})
test('should be chainable', () => {
const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const amount = '1000'
const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const result = creator
.mint(token, amount, toAddr)
.mint(token, amount, toAddr)
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(2)
})
})
describe('melt', () => {
test('should add melt operation to builder', () => {
const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const amount = '1000'
const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const result = creator.melt(token, amount, toAddr)
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(1)
})
test('should be chainable', () => {
const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const amount = '1000'
const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const result = creator
.melt(token, amount, toAddr)
.melt(token, amount, toAddr)
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(2)
})
})
describe('populate', () => {
test('should add populate operation to builder', () => {
const result = creator.populate()
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(1)
})
test('should be chainable', () => {
const result = creator
.from(mockAddresses)
.populate()
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(1)
})
})
describe('integration tests', () => {
test('should handle complete transaction flow', () => {
const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const amount = '1000'
const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const result = creator
.onNetwork('testnet')
.from(mockAddresses)
.mint(token, amount, toAddr)
.melt(token, amount, toAddr)
.populate()
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(3) // mint, melt, populate
expect(creator.network).toBe(Networks.testnet)
})
test('should handle token operations and populate', () => {
const token = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const amount = '1000'
const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const result = creator
.from(mockAddresses)
.sendTo(toAddr, amount)
.sendToToken(toAddr, amount, token)
.populate()
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(3) // sendTo, sendToToken, populate
})
test('should handle token creation', () => {
const result = creator
.from(mockAddresses)
.token('Test Token', 'TEST', 2, 'https://test.com', 'hash')
.populate()
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(2) // token, populate
})
test('should handle consolidate transaction', () => {
const toAddr = 'nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc'
const result = creator
.from(mockAddresses)
.consolidate(toAddr)
.populate()
expect(result).toBe(creator)
expect(creator.builder).toHaveLength(2) // consolidate, populate
})
})
describe('network handling', () => {
test('should set network correctly', () => {
const result = creator.onNetwork('testnet')
expect(result).toBe(creator)
expect(creator.network).toBe(Networks.testnet)
})
test('should default to mainnet', () => {
expect(creator.network).toBe(Networks.mainnet)
})
})
describe('error handling', () => {
test('should handle empty addresses array', () => {
const result = creator.from([])
expect(result).toBe(creator)
expect(creator['_availableAddresses']).toHaveLength(0)
})
test('should handle null/undefined addresses', () => {
// Test with addresses that don't have the address property
const invalidAddress = {} as WatchOnlyAddress
const result = creator.from(invalidAddress)
expect(result).toBe(creator)
// Should not add invalid addresses
expect(creator['_availableAddresses']).toHaveLength(0)
})
})
})