diff --git a/src/account.ts b/src/account.ts index 51b7105..f104d2f 100644 --- a/src/account.ts +++ b/src/account.ts @@ -14,7 +14,7 @@ import {PrivateKey, PublicKey, AccountModel} from './types'; import {Cryptography, Language, Strength} from './constants'; import { arrayPadStart, base58Decode, base58Encode, deepEqual, - isBrowser, stringToPublicOrPrivateKey + isBrowser, stringToPublicOrPrivateKey, publicOrPrivateKeyToString } from './utils'; import * as Requests from './requests'; @@ -71,7 +71,7 @@ export default class Account { }; } - public recover( + public retrieve( mnemonic: string, language: Language = Language.SimplifiedChinese, cryptography: Cryptography = Cryptography.EccFIPS @@ -166,6 +166,12 @@ export default class Account { }; } + export(password: string, privateKey: PrivateKey): string { + return btoa( + this.encryptPrivateKey(password, privateKey) + ); + } + private decryptPrivateKey(password: string, keyStr: string): string { const bytes = atob(keyStr).split('').map(s => s.charCodeAt(0)); const blockSize = 16; @@ -183,8 +189,8 @@ export default class Account { return td.decode(decryptedBytes); } - /* - private encryptPrivateKey(password: string, privateKey: PrivateKeyModel): string { + + private encryptPrivateKey(password: string, privateKey: PrivateKey): string { const keyStr = publicOrPrivateKeyToString(privateKey); const te = new TextEncoder(); const keyBytes: Uint8Array = te.encode(keyStr); @@ -198,7 +204,6 @@ export default class Account { const ts = Array.from(result).map((s: number) => String.fromCharCode(s)); return ts.join(''); } - */ private generateEntropy(strength: Strength): Uint8Array { if ((strength + 8) % 32 !== 0 || strength + 8 < 128 || strength + 8 > 256) { diff --git a/src/contract.ts b/src/contract.ts index 9718d0b..9499146 100644 --- a/src/contract.ts +++ b/src/contract.ts @@ -66,14 +66,14 @@ export default class Contract { // invoke contract - deployWasmContractRequests( + deployContractRequests( contractAccount: string, contractName: string, code: string, lang: string, initArgs: any ) { - + /* const newInitArgs = { ...initArgs }; @@ -113,6 +113,70 @@ export default class Contract { args: contractArgs }]; + return invokeRequests; + + */ + + return this.generateContractRequests('Deploy', contractAccount, contractName, code, lang, initArgs); + } + + upgradContractRequests( + contractAccount: string, + contractName: string, + code: string, + lang: string, + initArgs: any + ) { + return this.generateContractRequests('Upgrade', contractAccount, contractName, code, lang, initArgs); + } + + generateContractRequests( + methodName: string, + contractAccount: string, + contractName: string, + code: string, + lang: string, + initArgs: any + ) { + const newInitArgs = { + ...initArgs + }; + + const te = new TextEncoder(); + + Object.keys(initArgs).forEach(key => { + const bytes = te.encode(initArgs[key]); + const valueBuf: Array = []; + bytes.forEach(b => valueBuf.push(String.fromCharCode(b))); + newInitArgs[key] = btoa(valueBuf.join('')); + }); + + const desc = new Uint8Array([10, 1].concat(lang.split('').map(w => w.charCodeAt(0)))); + const descBuf = Object.values(desc).map(n => String.fromCharCode(n)); + + const args = { + account_name: contractAccount, + contract_name: contractName, + contract_desc: descBuf.join(''), + contract_code: code, + init_args: JSON.stringify(newInitArgs) + }; + + const contractArgs = { + ...args + }; + + Object.keys(contractArgs).forEach(key => { + // @ts-ignore + contractArgs[key] = btoa(contractArgs[key]); + }); + + const invokeRequests: ContractRequesttModel[] = [{ + module_name: 'xkernel', + method_name: methodName, + args: contractArgs + }]; + return invokeRequests; } diff --git a/src/index.ts b/src/index.ts index 5ccc551..34e3a60 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,6 +21,8 @@ import { } from './types'; import BN from 'bn.js'; +export {Cryptography, Language, Strength}; + export default class XuperSDK implements XuperSDKInterface { static instance: XuperSDK; private options: Options; @@ -61,14 +63,14 @@ export default class XuperSDK implements XuperSDKInterface { return this.accountInstance.create(language, strength, cryptography); } - recover( + retrieve( mnemonic: string, language: Language = Language.SimplifiedChinese, cryptography: Cryptography = Cryptography.EccFIPS, cache = false ): AccountModel { if (mnemonic) { - const account = this.accountInstance.recover(mnemonic, language, cryptography); + const account = this.accountInstance.retrieve(mnemonic, language, cryptography); if (cache) { this.account = account; return account; @@ -93,6 +95,22 @@ export default class XuperSDK implements XuperSDKInterface { } } + export(password: string): string { + + const acc = this.account; + + if (!password) { + throw Errors.PARAMETER_ERROR; + } + + if (acc) { + return this.accountInstance.export(password, acc.privateKey); + } + else { + throw Errors.ACCOUNT_NOT_EXIST; + } + } + checkAddress(address?: string): boolean { const addr = address || this.account?.address; @@ -163,11 +181,15 @@ export default class XuperSDK implements XuperSDKInterface { totalNeed = totalNeed.add(new BN(auth.fee || 0)); }); - // @ts-ignore - const preExecWithUtxos = await this.transactionInstance.preExecWithUTXO(node, chain, acc.address, totalNeed, Object.keys(authRequires), null, acc) - const preExecWithUtxosObj = JSON.parse(atob(preExecWithUtxos.ResponseData)); - - return this.transactionInstance.makeTransaction(acc, ti, authRequires, preExecWithUtxosObj); + try { + // @ts-ignore + const preExecWithUtxos = await this.transactionInstance.preExecWithUTXO(node, chain, acc.address, totalNeed, Object.keys(authRequires), null, acc) + const preExecWithUtxosObj = JSON.parse(atob(preExecWithUtxos.ResponseData)); + return this.transactionInstance.makeTransaction(acc, ti, authRequires, preExecWithUtxosObj); + } + catch (e) { + throw e; + } } async postTransaction(tx: TransactionModel, account?: AccountModel) { @@ -280,16 +302,31 @@ export default class XuperSDK implements XuperSDKInterface { code: string, lang: string, initArgs: any, + upgrade: boolean = false, account?: AccountModel ): Promise { const {node, chain} = this.options; - const invokeRequests = this.contractInstance.deployWasmContractRequests( - contractAccount, - contractName, - code, - lang, - initArgs - ); + + let invokeRequests: ContractRequesttModel[]; + + if (upgrade) { + invokeRequests = this.contractInstance.upgradContractRequests( + contractAccount, + contractName, + code, + lang, + initArgs + ) + } + else { + invokeRequests = this.contractInstance.deployContractRequests( + contractAccount, + contractName, + code, + lang, + initArgs + ); + } if (!account) { account = this.account; @@ -342,7 +379,7 @@ export default class XuperSDK implements XuperSDKInterface { methodName: string, moduleName: string, args: any, - address: string + account?: AccountModel ): Promise { const {node, chain} = this.options; const invokeRequests = this.contractInstance.invokeContract( @@ -350,7 +387,17 @@ export default class XuperSDK implements XuperSDKInterface { methodName, moduleName, args - ) + ); + + if (!account) { + account = this.account; + } + + if (!account) { + throw Errors.ACCOUNT_NOT_EXIST; + } + + const address = account.address; const authRequires: { [propName: string]: AuthModel } = {}; let totalNeed = new BN(0); @@ -362,10 +409,22 @@ export default class XuperSDK implements XuperSDKInterface { const preExecWithUtxos = await this.transactionInstance.preExecWithUTXO(node, chain, address, totalNeed, Object.keys(authRequires), invokeRequests) - console.log(preExecWithUtxos) const preExecWithUtxosObj = JSON.parse(atob(preExecWithUtxos.ResponseData)); - return new Promise(resolve => resolve(preExecWithUtxosObj)); + // return new Promise(resolve => resolve(preExecWithUtxosObj)); + + const gasUsed = preExecWithUtxosObj.response.gas_used || 0; + + const tx = await this.transactionInstance.makeTransaction(account, { + amount: '0', + fee: gasUsed.toString(), + to: '' + }, authRequires, preExecWithUtxosObj); + + return { + preExecutionTransaction: preExecWithUtxosObj, + transaction: tx + }; } transactionIdToHex(t: Required): string { diff --git a/src/interfaces.ts b/src/interfaces.ts index bd817f3..70fd77c 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -20,10 +20,12 @@ export default interface XuperSDKInterface extends AccountInterface, Transaction export interface AccountInterface { create(language: Language, strength: Strength, cryptography: Cryptography): AccountModel; - recover(mnemonic: string, language: Language, cryptography: Cryptography, cache?: boolean): AccountModel; + retrieve(mnemonic: string, language: Language, cryptography: Cryptography, cache?: boolean): AccountModel; import(password: string, privateKeyStr: string, cache?: boolean): AccountModel; + export(password: string): string; + checkAddress(address?: string): boolean; checkMnemonic(mnemonic: string, language: Language): boolean; @@ -54,7 +56,7 @@ export interface ContractInterface { getContracts(target: string): Promise; - deployWasmContract(contractAccount: string, contractName: string, code: string, lang: string, initArgs: any, account?: AccountModel): Promise; + deployWasmContract(contractAccount: string, contractName: string, code: string, lang: string, initArgs: any, upgrade: boolean, account?: AccountModel): Promise; // upgradeContract(): Promise; // imvokeContract(): Promise; diff --git a/test/account.test.ts b/test/account.test.ts index b6a8a8a..8fc02d1 100644 --- a/test/account.test.ts +++ b/test/account.test.ts @@ -3,19 +3,18 @@ * Created by SmilingXinyi on 2020/7/2 */ -import XuperSDK from '../src'; +import XuperSDK, {Cryptography, Language} from '../src'; import {AccountModel} from '../src/types'; import {isBrowser} from '../src/utils'; -import {Cryptography, Language} from '../src/constants'; -import XuperErrors, {XuperError} from '../src/error'; +// import XuperErrors, {XuperError} from '../src/error'; isBrowser && require('whatwg-fetch'); const - node = process.env.HOST || 'http://localhost:8098', - chain = process.env.CHAIN || 'xuper', - mnemonic = '玉 脸 驱 协 介 跨 尔 籍 杆 伏 愈 即', - address = 'nuSMPvo6UUoTaT8mMQmHbfiRbJNbAymGh'; + node = process.env.HOST!, + chain = process.env.CHAIN!, + mnemonic = process.env.TEST_MNEMONIC!, + address = process.env.TEST_ADDRESS!; describe('Xuper SDK account ——', () => { describe('create an account with mnemonic', () => { @@ -36,14 +35,14 @@ describe('Xuper SDK account ——', () => { // Todo: export encrypro key }); - describe('recover the account', () => { + describe('retrieve the account', () => { test('from mnemonic should return account model', () => { const xsdk = new XuperSDK({ node, chain }); - const account: AccountModel = xsdk.recover( + const account: AccountModel = xsdk.retrieve( mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS @@ -69,96 +68,86 @@ describe('Xuper SDK account ——', () => { // Todo: Import private key }); +}); - describe('check the address balance', () => { - test('should return balance structure', async () => { - const xsdk = new XuperSDK({ - node, - chain - }); +test('create an account with mnemonic should return account model', () => { + const xsdk = new XuperSDK({ + node, + chain + }); - const balance = await xsdk.getBalance('nuSMPvo6UUoTaT8mMQmHbfiRbJNbAymGh'); - console.log(balance); - expect(balance).toHaveProperty('bcs'); - expect(balance.bcs).toHaveLength(1); - expect(balance.bcs[0]).toHaveProperty('bcname', chain); - expect(balance.bcs[0]).toHaveProperty('balance'); - }); + const account: AccountModel = xsdk.create(); - test('of recovered account should return balance structure', async () => { - const xsdk = new XuperSDK({ - node, - chain - }); - - xsdk.recover(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); + expect(account).toHaveProperty('mnemonic'); + expect(account).toHaveProperty('privateKey'); + expect(account).toHaveProperty('publicKey'); + expect(account).toHaveProperty('address'); +}); - const balance = await xsdk.getBalance(); - expect(balance).toHaveProperty('bcs'); - expect(balance.bcs).toHaveLength(1); - expect(balance.bcs[0]).toHaveProperty('bcname', chain); - expect(balance.bcs[0]).toHaveProperty('balance'); - }); +test('retrieve the account from mnemonic should return account model', () => { + const xsdk = new XuperSDK({ + node, + chain + }); - test('of empty address should return error message with wrong parameter', async () => { - const xsdk = new XuperSDK({ - node, - chain - }); + const account: AccountModel = xsdk.retrieve( + mnemonic, + Language.SimplifiedChinese, + Cryptography.EccFIPS + ); + + expect(account).toHaveProperty('mnemonic'); + expect(account).toHaveProperty('privateKey'); + expect(account).toHaveProperty('publicKey'); + expect(account).toHaveProperty('address'); + expect(account.address).toBe(address); +}); - const balance = xsdk.getBalance.bind(xsdk); +test('retrieve the account from private key return accout model', () => { + const xsdk = new XuperSDK({ + node, + chain + }); - expect(balance).toThrow( - XuperError.or([ - XuperErrors.ACCOUNT_NOT_EXIST, - XuperErrors.PARAMETER_ERROR - ])); - }); + const account = xsdk.retrieve( + mnemonic, + Language.SimplifiedChinese, + Cryptography.EccFIPS, + true + ); - test('detail should return balance structure', async () => { + const encryptPrivateKeyString = xsdk.export('123456'); + const retrievedAccount = xsdk.import('123456', encryptPrivateKeyString); - const xsdk = new XuperSDK({ - node, - chain - }); + expect(retrievedAccount.address).toEqual(account.address); + expect(retrievedAccount.privateKey.Curvname).toEqual(account.privateKey.Curvname); + expect(retrievedAccount.privateKey.X).toEqual(account.privateKey.X); + expect(retrievedAccount.privateKey.Y).toEqual(account.privateKey.Y); +}); - const balanceDetail = await xsdk.getBalanceDetail('nuSMPvo6UUoTaT8mMQmHbfiRbJNbAymGh'); - console.log(balanceDetail); - expect(balanceDetail).toHaveProperty('tfds'); - expect(balanceDetail.tfds).toHaveLength(1); - expect(balanceDetail.tfds[0]).toHaveProperty('bcname', chain); - expect(balanceDetail.tfds[0]).toHaveProperty('tfd'); - expect(balanceDetail.tfds[0].tfd).toHaveLength(2); - expect(balanceDetail.tfds[0].tfd[0]).toHaveProperty('balance'); - expect(balanceDetail.tfds[0].tfd[0]).toHaveProperty('isFrozen'); - expect(balanceDetail.tfds[0].tfd[1]).toHaveProperty('balance'); - }); +test('check the mnemonic is correct should return true', () => { + const xsdk = new XuperSDK({ + node, + chain }); - test('check the mnemonic valid should return true', () => { - const xsdk = new XuperSDK({ - node, - chain - }); + const result = xsdk.checkMnemonic( + mnemonic, + Language.SimplifiedChinese + ); - const result = xsdk.checkMnemonic( - mnemonic, - Language.SimplifiedChinese - ); + expect(result).toBeTruthy(); +}); - expect(result).toBeTruthy(); +test('check the address is correct should return true', () => { + const xsdk = new XuperSDK({ + node, + chain }); - test('check the address valid should return true', () => { - const xsdk = new XuperSDK({ - node, - chain - }); - - const result = xsdk.checkAddress( - address - ); + const result = xsdk.checkAddress( + address + ); - expect(result).toBeTruthy(); - }); + expect(result).toBeTruthy(); }); diff --git a/test/contract.test.ts b/test/contract.test.ts index 273ed32..1a86109 100644 --- a/test/contract.test.ts +++ b/test/contract.test.ts @@ -2,11 +2,11 @@ * @file (contract) * Created by baidu on 2020/7/20 */ -jest.setTimeout(1000000000); -import XuperSDK from '../src'; +jest.setTimeout(100000000); + +import XuperSDK, {Cryptography, Language} from '../src'; import {isBrowser} from '../src/utils'; -import {Cryptography, Language} from '../src/constants'; isBrowser && require('whatwg-fetch'); @@ -24,7 +24,7 @@ describe('Xuper SDK Contract:', () => { chain }); - xsdk.recover( + xsdk.retrieve( mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, @@ -39,42 +39,42 @@ describe('Xuper SDK Contract:', () => { expect(result.header).not.toHaveProperty('error'); }); - test('get the current account contract list should return contracts', async () => { + test('get the address contract accounts should return contarct account list', async () => { const xsdk = new XuperSDK({ node, chain }); - xsdk.recover( + xsdk.retrieve( mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true ); - const result = await xsdk.getContracts(address); - console.log(JSON.stringify(result.contracts, null, 4)); + const result = await xsdk.getContractAccounts(); + console.warn(result); expect(result.header).toHaveProperty('logid'); + expect(result).toHaveProperty('bcname'); + expect(result).toHaveProperty('account'); }); - test('get the address contract accounts should return contarct account list', async () => { + test('get the contract list of current account should return contracts', async () => { const xsdk = new XuperSDK({ node, chain }); - xsdk.recover( + xsdk.retrieve( mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true ); - const result = await xsdk.getContractAccounts(); - console.warn(result); + const result = await xsdk.getContracts(address); + console.log(JSON.stringify(result, null, 4)); expect(result.header).toHaveProperty('logid'); - expect(result).toHaveProperty('bcname'); - expect(result).toHaveProperty('account'); }); test('deploy new wasm contract should return transaction info and result of post', async () => { @@ -83,7 +83,7 @@ describe('Xuper SDK Contract:', () => { chain }); - xsdk.recover( + xsdk.retrieve( mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, @@ -106,7 +106,7 @@ describe('Xuper SDK Contract:', () => { console.error(contractName); const result = await xsdk.deployWasmContract( - 'XC1234567890497536@xuper', + 'XC1234567890598143@xuper', contractName, codeBuf.join(''), 'c', { @@ -121,29 +121,74 @@ describe('Xuper SDK Contract:', () => { console.warn(r); }); - test('invoke contract', async () => { + test('deploy ne result of post', async () => { const xsdk = new XuperSDK({ node, chain }); - xsdk.recover( + xsdk.retrieve( mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true ); + const codeBuf: string[] = []; + + if (isBrowser) { + // @ts-ignore + window.file.forEach(n => codeBuf.push(String.fromCharCode(n))); + } else { + const fs = require('fs'); + const wasm = Uint8Array.from(fs.readFileSync(`${__dirname}/wasm/counter.wasm`)); + wasm.forEach(n => codeBuf.push(String.fromCharCode(n))); + } - // const result = await xsdk.invokeContract('counter715', 'get', 'wasm', { - const result = await xsdk.invokeContarct('counter347', 'get', 'wasm', { - Bucket: 'XCAccount', - Key: 'XC1234567890145964@xuper' - }, address); + const contractName = `counter${~~(Math.random() * 10 ** 3 - 10 ** 3) + 10 ** 3}`; + + console.error(contractName); + + const result = await xsdk.deployWasmContract( + 'XC1234567890598143@xuper', + 'counter500', + codeBuf.join(''), + 'c', { + creator: address + }, + true + ); console.warn(JSON.stringify(result, null, 4)); + const r = await xsdk.postTransaction(result.transaction); + + console.warn(r); + }); + + test('invoke contract', async () => { + const xsdk = new XuperSDK({ + node, + chain + }); + + const account = xsdk.retrieve( + mnemonic, + Language.SimplifiedChinese, + Cryptography.EccFIPS, + true + ); + + const {transaction} = + await xsdk.invokeContarct('counter500', 'increase', 'wasm', {}, account); + + console.warn(JSON.stringify(transaction, null, 4)); + + const result = await xsdk.postTransaction(transaction); + expect(result.header).toHaveProperty('logid'); expect(result.header).not.toHaveProperty('error'); }); + + // Todo: Upgrade }); diff --git a/test/plugins.test.ts b/test/plugins.test.ts index 1d2f7f5..9661711 100644 --- a/test/plugins.test.ts +++ b/test/plugins.test.ts @@ -40,7 +40,8 @@ describe('Xuper SDK ——', () => { })] }); - xsdk.recover(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); + xsdk.retrieve(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); + try { const tx = await xsdk.transfer({ @@ -81,7 +82,7 @@ describe('Xuper SDK ——', () => { })] }); - xsdk.recover(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); + xsdk.retrieve(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); try { const tx = await xsdk.transfer({ @@ -111,7 +112,7 @@ describe('Xuper SDK ——', () => { plugins: [CFCAPlugin()] }); - xsdk.recover(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); + xsdk.retrieve(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); try { const tx = await xsdk.transfer({ diff --git a/test/transaction.test.ts b/test/transaction.test.ts index 6b33200..8c6cf89 100644 --- a/test/transaction.test.ts +++ b/test/transaction.test.ts @@ -9,30 +9,29 @@ import {Cryptography, Language} from '../src/constants'; isBrowser && require('whatwg-fetch'); -const - node = process.env.HOST || 'http://localhost:8098', - chain = process.env.CHAIN || 'xuper', - mnemonic = '玉 脸 驱 协 介 跨 尔 籍 杆 伏 愈 即'; +const node = process.env.SERVER!, chain = process.env.CHAIN!, + mnemonic = process.env.TEST_MNEMONIC!, address = process.env.TEST_ADDRESS; -describe('Xuper SDK transaction ——', () => { - describe('check status of chain', () => { - test('should return the blockchain status data structure', async () => { - const xsdk = new XuperSDK({node, chain}); +describe('Generate transaction', () => { + test('shoudle return transaction structure', async () => { + const xsdk = new XuperSDK({node, chain}); - xsdk.recover(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); + xsdk.retrieve(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); - try { - const tx = await xsdk.transfer({ - to: process.env.TEST_TARGET_ADDRESS || '', - amount: '100', - fee: '100' - }); - - console.log(tx); - } - catch (e) { - throw e; - } + const tx = await xsdk.transfer({ + to: process.env.TEST_TARGET_ADDRESS || '', + amount: '100', + fee: '100' }); + + expect(tx).toHaveProperty('txid'); + expect(tx).toHaveProperty('initiator_signs'); + expect(tx).toHaveProperty('initiator', address); + expect(tx).toHaveProperty('coinbase', false); + expect(tx).toHaveProperty('autogen', false); + expect(tx).toHaveProperty('version', 1); + expect(tx).toHaveProperty('tx_inputs'); + expect(tx).toHaveProperty('tx_outputs'); + expect(tx).toHaveProperty('auth_require', []); }); }); diff --git a/test/xuper.test.ts b/test/xuper.test.ts index c7e36e4..974cf21 100644 --- a/test/xuper.test.ts +++ b/test/xuper.test.ts @@ -2,17 +2,15 @@ * @file Xuper SDK test * Created by SmilingXinyi on 2020/6/2 */ -jest.setTimeout(10000); -import XuperSDK from '../src'; +import XuperSDK, {Cryptography, Language} from '../src'; import {isBrowser} from '../src/utils'; isBrowser && require('whatwg-fetch'); -const - node = process.env.HOST!, - chain = process.env.CHAIN!; - +const node = process.env.SERVER!, chain = process.env.CHAIN!, + mnemonic = process.env.TEST_MNEMONIC!, address = process.env.TEST_ADDRESS!, + targetAddress = process.env.TEST_TARGET_MNEMONIC!; test('check status of xuperchain should return current status', async () => { const xsdk = new XuperSDK({node, chain}); @@ -28,3 +26,39 @@ test('convert txid to hex string', () => { const hexTxid = xsdk.transactionIdToHex('95z7TJlLI6cFHGL+rQp307LDwPlltErTxrxuN9gaJdI='); expect(hexTxid).toEqual('f79cfb4c994b23a7051c62fead0a77d3b2c3c0f965b44ad3c6bc6e37d81a25d2'); }); + +describe('Get the balance', () => { + test('of current account', async () => { + const xsdk = new XuperSDK({node, chain}); + xsdk.retrieve(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); + const result = await xsdk.getBalance(); + expect(result).toHaveProperty('header'); + expect(result).toHaveProperty('address', address); + expect(result).toHaveProperty('bcs'); + }); + + test('detail of current account', async () => { + const xsdk = new XuperSDK({node, chain}); + xsdk.retrieve(mnemonic, Language.SimplifiedChinese, Cryptography.EccFIPS, true); + const result = await xsdk.getBalanceDetail(); + expect(result).toHaveProperty('header'); + expect(result).toHaveProperty('address', address); + expect(result).toHaveProperty('tfds'); + }); + + test(`of target account`, async () => { + const xsdk = new XuperSDK({node, chain}); + const result = await xsdk.getBalance(targetAddress); + expect(result).toHaveProperty('header'); + expect(result).toHaveProperty('address', targetAddress); + expect(result).toHaveProperty('bcs'); + }); + + test(`detail of target account`, async () => { + const xsdk = new XuperSDK({node, chain}); + const result = await xsdk.getBalanceDetail(targetAddress); + expect(result).toHaveProperty('header'); + expect(result).toHaveProperty('address', targetAddress); + expect(result).toHaveProperty('tfds'); + }); +});