Upgrading from @kadena/client 0.x to 1.0.0
The highlights of the difference between 0.x and 1.0.0 are:
- the expression generation is separate from transaction building. This allows for multiple statements per transaction
- the client is it's own separate entity
- signing is applied on a vanilla JS Object
Here are two examples of old to new rewrites
Sending a transaction 'transfer'
Old implementation
async function transaction( sender: string, senderPublicKey: string, receiver: string, amount: IPactDecimal,): Promise<void> { const unsignedTransaction = Pact.modules.coin .transfer(sender, receiver, amount) .addCap('coin.GAS', senderPublicKey) .addCap('coin.TRANSFER', senderPublicKey, sender, receiver, amount) .setMeta({ sender }, 'testnet04'); const res = await signWithChainweaver(unsignedTransaction); const sendRequests = res.map((tx) => { console.log('sending transaction', tx.code); return tx.send(testnetChain1ApiHost); }); const sendResponses = await Promise.all(sendRequests); sendResponses.map(async function (sendResponse: SendResponse): Promise<void> { const requestKey = (await sendRequests[0]).requestKeys[0]; await pollMain(requestKey); console.log(`Transaction '${requestKey}' finished`); });} async function pollMain(...requestKeys: string[]): Promise<void> { // ... some code to poll the status of the requestKeys}
async function transaction( sender: string, senderPublicKey: string, receiver: string, amount: IPactDecimal,): Promise<void> { const unsignedTransaction = Pact.modules.coin .transfer(sender, receiver, amount) .addCap('coin.GAS', senderPublicKey) .addCap('coin.TRANSFER', senderPublicKey, sender, receiver, amount) .setMeta({ sender }, 'testnet04'); const res = await signWithChainweaver(unsignedTransaction); const sendRequests = res.map((tx) => { console.log('sending transaction', tx.code); return tx.send(testnetChain1ApiHost); }); const sendResponses = await Promise.all(sendRequests); sendResponses.map(async function (sendResponse: SendResponse): Promise<void> { const requestKey = (await sendRequests[0]).requestKeys[0]; await pollMain(requestKey); console.log(`Transaction '${requestKey}' finished`); });} async function pollMain(...requestKeys: string[]): Promise<void> { // ... some code to poll the status of the requestKeys}
New implementation
const NETWORK_ID: string = 'testnet04'; async function transfer( sender: string, senderPublicKey: string, receiver: string, amount: IPactDecimal,): Promise<void> { const transaction = Pact.builder .execution( // pact expression Pact.modules.coin.transfer(sender, receiver, amount), ) // add signers .addSigner(senderPublicKey, (withCapability) => [ // add capabilities withCapability('coin.GAS'), withCapability('coin.TRANSFER', sender, receiver, amount), ]) // set chainId and sender .setMeta({ chainId: '0', sender }) .setNetworkId(NETWORK_ID) // will create a IUnsignedTransaction { cmd, hash, sigs } .createTransaction(); const signedTx = await signWithChainweaver(transaction); // create generic client const client = createClient(apiHostGenerator); // check if all necessary signatures are added if (isSignedTransaction(signedTx)) { const transactionDescriptor = await client.submit(signedTx); const response = await client.listen(transactionDescriptor, {}); if (response.result.status === 'failure') { throw response.result.error; } else { console.log(response.result); } }} transfer(senderAccount, senderPublicKey, receiverAccount, { decimal: '13.37',}).catch(console.error);
const NETWORK_ID: string = 'testnet04'; async function transfer( sender: string, senderPublicKey: string, receiver: string, amount: IPactDecimal,): Promise<void> { const transaction = Pact.builder .execution( // pact expression Pact.modules.coin.transfer(sender, receiver, amount), ) // add signers .addSigner(senderPublicKey, (withCapability) => [ // add capabilities withCapability('coin.GAS'), withCapability('coin.TRANSFER', sender, receiver, amount), ]) // set chainId and sender .setMeta({ chainId: '0', sender }) .setNetworkId(NETWORK_ID) // will create a IUnsignedTransaction { cmd, hash, sigs } .createTransaction(); const signedTx = await signWithChainweaver(transaction); // create generic client const client = createClient(apiHostGenerator); // check if all necessary signatures are added if (isSignedTransaction(signedTx)) { const transactionDescriptor = await client.submit(signedTx); const response = await client.listen(transactionDescriptor, {}); if (response.result.status === 'failure') { throw response.result.error; } else { console.log(response.result); } }} transfer(senderAccount, senderPublicKey, receiverAccount, { decimal: '13.37',}).catch(console.error);
Read from the blockchain 'getBalance'
Old implementation
async function getBalance(account: string): Promise<void> { // generation of transaction and expression as one, and the client is part of the transaction const res = await Pact.modules.coin['get-balance'](account).local( 'http://host.com/chain/0/pact', ); console.log(res);} const myAccount: string = 'k:554754f48b16df24b552f6832dda090642ed9658559fef9f3ee1bb4637ea7c94'; getBalance(myAccount).catch(console.error);
async function getBalance(account: string): Promise<void> { // generation of transaction and expression as one, and the client is part of the transaction const res = await Pact.modules.coin['get-balance'](account).local( 'http://host.com/chain/0/pact', ); console.log(res);} const myAccount: string = 'k:554754f48b16df24b552f6832dda090642ed9658559fef9f3ee1bb4637ea7c94'; getBalance(myAccount).catch(console.error);
New implementation:
async function getBalance(account: string): Promise<void> { // `Pact.builder.execution` accepts a number of `Pact.modules.<module>.<fun>` calls const transaction = Pact.builder .execution(Pact.modules.coin['get-balance'](account)) .setMeta({ chainId: '1' }) .createTransaction(); // client creation is separate from the transaction builder const staticClient = createClient('http://host.com/chain/0/pact'); const genericClient = createClient( ({ networkId, chainId }) => `http://${networkId}.host.com/chain/${chainId}/pact`, ); const res = await staticClient.local(transaction, { preflight: false, signatureVerification: false, }); console.log(res);} getBalance(account).catch(console.error);
async function getBalance(account: string): Promise<void> { // `Pact.builder.execution` accepts a number of `Pact.modules.<module>.<fun>` calls const transaction = Pact.builder .execution(Pact.modules.coin['get-balance'](account)) .setMeta({ chainId: '1' }) .createTransaction(); // client creation is separate from the transaction builder const staticClient = createClient('http://host.com/chain/0/pact'); const genericClient = createClient( ({ networkId, chainId }) => `http://${networkId}.host.com/chain/${chainId}/pact`, ); const res = await staticClient.local(transaction, { preflight: false, signatureVerification: false, }); console.log(res);} getBalance(account).catch(console.error);