UNPKG

dimension-js-sdk-cy

Version:

SDK to interact with the Dimension blockchain - just for learning

516 lines (462 loc) 16.9 kB
import { expect, assert } from 'chai'; import { Keys, DeployUtil, CLValueBuilder } from '../../src/lib'; import { humanizerTTL, dehumanizerTTL } from '../../src/lib/DeployUtil'; import { TypedJSON } from 'typedjson'; const testDeploy = () => { const senderKey = Keys.Ed25519.new(); const recipientKey = Keys.Ed25519.new(); const networkName = 'dimension-test'; const paymentAmount = 10000000000000; const transferAmount = 10; const transferId = 34; let deployParams = new DeployUtil.DeployParams( senderKey.publicKey, networkName ); let session = DeployUtil.ExecutableDeployItem.newTransfer( transferAmount, recipientKey.publicKey, undefined, transferId ); let payment = DeployUtil.standardPayment(paymentAmount); let deploy = DeployUtil.makeDeploy(deployParams, session, payment); deploy = DeployUtil.signDeploy(deploy, senderKey); return deploy; } describe('DeployUtil', () => { it('should stringify/parse DeployHeader correctly', function() { const ed25519Key = Keys.Ed25519.new(); const deployHeader = new DeployUtil.DeployHeader( ed25519Key.publicKey, 123456, 654321, 10, Uint8Array.from(Array(32).fill(42)), [Uint8Array.from(Array(32).fill(2))], 'dimension-test' ); const serializer = new TypedJSON(DeployUtil.DeployHeader); const json = serializer.stringify(deployHeader); const deployHeader1 = serializer.parse(json); expect(deployHeader1).to.deep.equal(deployHeader); }); it('should allow to extract data from Transfer', function() { const senderKey = Keys.Ed25519.new(); const recipientKey = Keys.Ed25519.new(); const networkName = 'dimension-test'; const paymentAmount = 10000000000000; const transferAmount = 10; const id = 34; let deployParams = new DeployUtil.DeployParams( senderKey.publicKey, networkName ); let session = DeployUtil.ExecutableDeployItem.newTransfer( transferAmount, recipientKey.publicKey, undefined, id ); let payment = DeployUtil.standardPayment(paymentAmount); let deploy = DeployUtil.makeDeploy(deployParams, session, payment); deploy = DeployUtil.signDeploy(deploy, senderKey); deploy = DeployUtil.signDeploy(deploy, recipientKey); // Serialize deploy to JSON. let json = DeployUtil.deployToJson(deploy); // Deserialize deploy from JSON. deploy = DeployUtil.deployFromJson(json).unwrap(); assert.isTrue(deploy.isTransfer()); assert.isTrue(deploy.isStandardPayment()); assert.deepEqual(deploy.header.account, senderKey.publicKey); assert.deepEqual( deploy.payment .getArgByName('amount')! .value() .toNumber(), paymentAmount ); assert.deepEqual( deploy.session .getArgByName('amount')! .value() .toNumber(), transferAmount ); assert.deepEqual( deploy.session.getArgByName('target'), recipientKey.publicKey ); assert.deepEqual( deploy.session .getArgByName('id')! .value() .unwrap() .value() .toNumber(), id ); assert.deepEqual(deploy.approvals[0].signer, senderKey.accountHex()); assert.deepEqual(deploy.approvals[1].signer, recipientKey.accountHex()); }); it('should allow to add arg to Deploy', function() { const senderKey = Keys.Ed25519.new(); const recipientKey = Keys.Ed25519.new(); const networkName = 'dimension-test'; const paymentAmount = 10000000000000; const transferAmount = 10; const id = 34; const customId = 60; let deployParams = new DeployUtil.DeployParams( senderKey.publicKey, networkName ); let session = DeployUtil.ExecutableDeployItem.newTransfer( transferAmount, recipientKey.publicKey, undefined, id ); let payment = DeployUtil.standardPayment(paymentAmount); let oldDeploy = DeployUtil.makeDeploy(deployParams, session, payment); // Add new argument. let deploy = DeployUtil.addArgToDeploy( oldDeploy, 'custom_id', CLValueBuilder.u32(customId) ); // Serialize and deserialize deploy. let json = DeployUtil.deployToJson(deploy); deploy = DeployUtil.deployFromJson(json).unwrap(); assert.deepEqual( deploy.session .getArgByName('custom_id')! .value() .toNumber(), customId ); assert.isTrue(deploy.isTransfer()); assert.isTrue(deploy.isStandardPayment()); assert.deepEqual(deploy.header.account, senderKey.publicKey); assert.deepEqual( deploy.payment .getArgByName('amount')! .value() .toNumber(), paymentAmount ); assert.deepEqual( deploy.session .getArgByName('amount')! .value() .toNumber(), transferAmount ); assert.deepEqual( deploy.session.getArgByName('target'), recipientKey.publicKey ); assert.deepEqual( deploy.session .getArgByName('id')! .value() .unwrap() .value() .toNumber(), id ); assert.notEqual(oldDeploy.hash, deploy.hash); assert.notEqual(oldDeploy.header.bodyHash, deploy.header.bodyHash); }); it('should not allow to add arg to a signed Deploy', function() { const senderKey = Keys.Ed25519.new(); const recipientKey = Keys.Ed25519.new(); const networkName = 'dimension-test'; const paymentAmount = 10000000000000; const transferAmount = 10; const id = 34; const customId = 60; let deployParams = new DeployUtil.DeployParams( senderKey.publicKey, networkName ); let session = DeployUtil.ExecutableDeployItem.newTransfer( transferAmount, recipientKey.publicKey, undefined, id ); let payment = DeployUtil.standardPayment(paymentAmount); let deploy = DeployUtil.makeDeploy(deployParams, session, payment); deploy = DeployUtil.signDeploy(deploy, senderKey); expect(() => { // Add new argument. DeployUtil.addArgToDeploy(deploy, 'custom_id', CLValueBuilder.u32(customId)); }).to.throw('Can not add argument to already signed deploy.'); }); it('should allow to extract additional args from Transfer.', function () { // const from = Keys.Ed25519.new(); const from = Keys.Secp256K1.new(); const to = Keys.Ed25519.new(); const networkName = 'dimension-test'; const paymentAmount = 10000000000000; const transferAmount = 10; const id = 34; let deployParams = new DeployUtil.DeployParams(from.publicKey, networkName); let session = DeployUtil.ExecutableDeployItem.newTransfer( transferAmount, to.publicKey, undefined, id ); let payment = DeployUtil.standardPayment(paymentAmount); let deploy = DeployUtil.makeDeploy(deployParams, session, payment); let transferDeploy = DeployUtil.addArgToDeploy( deploy, 'fromPublicKey', from.publicKey ); assert.deepEqual( transferDeploy.session.getArgByName('fromPublicKey'), from.publicKey ); let newTransferDeploy = DeployUtil.deployFromJson( DeployUtil.deployToJson(transferDeploy) ).unwrap(); assert.deepEqual( newTransferDeploy?.session.getArgByName('fromPublicKey'), from.publicKey ); }); it('Should not allow for to deserialize a deploy from JSON with a wrong deploy hash', function () { let deploy = testDeploy(); let json = DeployUtil.deployToJson(deploy); Object.assign(json.deploy, { hash: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" }); assert.isTrue(DeployUtil.deployFromJson(json).err); }); it('Should not allow for to deserialize a deploy from JSON with a wrong body_hash', function () { let deploy = testDeploy(); let json = DeployUtil.deployToJson(deploy); let header = Object(json.deploy)['header']; header['body_hash'] = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; Object.assign(json.deploy, { header }); assert.isTrue(DeployUtil.deployFromJson(json).err); }); it('Should convert ms to humanized string', function () { const strTtl30m = humanizerTTL(1800000); const strTtl45m = humanizerTTL(2700000); const strTtl1h = humanizerTTL(3600000); const strTtl1h30m = humanizerTTL(5400000); const strTtl1day = humanizerTTL(86400000); const strTtlCustom = humanizerTTL(86103000); expect(strTtl30m).to.be.eq("30m"); expect(strTtl45m).to.be.eq("45m"); expect(strTtl1h).to.be.eq("1h"); expect(strTtl1h30m).to.be.eq("1h 30m"); expect(strTtl1day).to.be.eq("1day"); expect(strTtlCustom).to.be.eq("23h 55m 3s"); }); it('Should convert humanized string to ms', function () { const msTtl30m = dehumanizerTTL("30m"); const msTtl45m = dehumanizerTTL("45m"); const msTtl1h = dehumanizerTTL("1h"); const msTtl1h30m = dehumanizerTTL("1h 30m"); const msTtl1day = dehumanizerTTL("1day"); const msTtlCustom = dehumanizerTTL("23h 55m 3s"); expect(msTtl30m).to.be.eq(1800000); expect(msTtl45m).to.be.eq(2700000); expect(msTtl1h).to.be.eq(3600000); expect(msTtl1h30m).to.be.eq(5400000); expect(msTtl1day).to.be.eq(86400000); expect(msTtlCustom).to.be.eq(86103000); }); it('Should not allow to create new transfer without providing transfer-id', () => { const recipientKey = Keys.Ed25519.new(); const transferAmount = 10; /* @ts-ignore */ const badFn = () => DeployUtil.ExecutableDeployItem.newTransfer( transferAmount, recipientKey.publicKey, undefined, ); expect(badFn).to.throw('transfer-id missing in new transfer.'); }); it('Should be able create new transfer without providing transfer-id using newTransferWithOptionalTransferId()', () => { const recipientKey = Keys.Ed25519.new(); const transferAmount = 10; const goodFn = () => DeployUtil.ExecutableDeployItem.newTransferWithOptionalTransferId( transferAmount, recipientKey.publicKey, ); expect(goodFn).to.not.throw(); }); it('newTransferToUniqAddress should construct proper deploy', () => { const senderKey = Keys.Ed25519.new(); const recipientKey = Keys.Ed25519.new(); const networkName = 'dimension-test'; const paymentAmount = 10000000000000; const transferAmount = 10; const transferId = 34; const uniqAddress = new DeployUtil.UniqAddress(recipientKey.publicKey, transferId); let deploy = DeployUtil.ExecutableDeployItem.newTransferToUniqAddress( senderKey.publicKey, uniqAddress, transferAmount, paymentAmount, networkName ); deploy = DeployUtil.signDeploy(deploy, senderKey); assert.isTrue(deploy.isTransfer()); assert.isTrue(deploy.isStandardPayment()); assert.deepEqual(deploy.header.account, senderKey.publicKey); assert.deepEqual( deploy.payment.getArgByName('amount')!.value().toNumber(), paymentAmount ); assert.deepEqual( deploy.session.getArgByName('amount')!.value().toNumber(), transferAmount ); assert.deepEqual( deploy.session.getArgByName('target'), recipientKey.publicKey ); assert.deepEqual( deploy.session .getArgByName('id')! .value() .unwrap() .value() .toNumber(), transferId ); }); it('DeployUtil.UniqAddress should serialize and deserialize', () => { const recipientKey = Keys.Ed25519.new(); const hexAddress = recipientKey.publicKey.toHex(); const transferId = "80172309"; const transferIdHex = "0x04c75515"; const uniqAddress = new DeployUtil.UniqAddress(recipientKey.publicKey, transferId); expect(uniqAddress).to.be.instanceof(DeployUtil.UniqAddress); expect(uniqAddress.toString()).to.be.eq(`${hexAddress}-${transferIdHex}`); }); it('DeployUtil.deployToBytes should produce correct byte representation.', () => { let deploy = DeployUtil.deployFromJson({ "deploy": { "hash": "d7a68bbe656a883d04bba9f26aa340dbe3f8ec99b2adb63b628f2bc920431998", "header": { "account": "017f747b67bd3fe63c2a736739dfe40156d622347346e70f68f51c178a75ce5537", "timestamp": "2021-05-04T14:20:35.104Z", "ttl": "30m", "gas_price": 2, "body_hash": "f2e0782bba4a0a9663cafc7d707fd4a74421bc5bfef4e368b7e8f38dfab87db8", "dependencies": [ "0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f", "1010101010101010101010101010101010101010101010101010101010101010" ], "chain_name": "mainnet" }, "payment": { "ModuleBytes": { "module_bytes": "", "args": [ [ "amount", { "cl_type": "U512", "bytes": "0400ca9a3b", "parsed": "1000000000" } ] ] } }, "session": { "Transfer": { "args": [ [ "amount", { "cl_type": "U512", "bytes": "05005550b405", "parsed": "24500000000" } ], [ "target", { "cl_type": { "ByteArray": 32 }, "bytes": "0101010101010101010101010101010101010101010101010101010101010101", "parsed": "0101010101010101010101010101010101010101010101010101010101010101" } ], [ "id", { "cl_type": { "Option": "U64" }, "bytes": "01e703000000000000", "parsed": 999 } ], [ "additional_info", { "cl_type": "String", "bytes": "1000000074686973206973207472616e73666572", "parsed": "this is transfer" } ] ] } }, "approvals": [ { "signer": "017f747b67bd3fe63c2a736739dfe40156d622347346e70f68f51c178a75ce5537", "signature": "0195a68b1a05731b7014e580b4c67a506e0339a7fffeaded9f24eb2e7f78b96bdd900b9be8ca33e4552a9a619dc4fc5e4e3a9f74a4b0537c14a5a8007d62a5dc06" } ] } }).unwrap(); let expected = "017f747b67bd3fe63c2a736739dfe40156d622347346e70f68f51c178a75ce5537a087c0377901000040771b00000000000200000000000000f2e0782bba4a0a9663cafc7d707fd4a74421bc5bfef4e368b7e8f38dfab87db8020000000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f1010101010101010101010101010101010101010101010101010101010101010070000006d61696e6e6574d7a68bbe656a883d04bba9f26aa340dbe3f8ec99b2adb63b628f2bc92043199800000000000100000006000000616d6f756e74050000000400ca9a3b08050400000006000000616d6f756e740600000005005550b40508060000007461726765742000000001010101010101010101010101010101010101010101010101010101010101010f200000000200000069640900000001e7030000000000000d050f0000006164646974696f6e616c5f696e666f140000001000000074686973206973207472616e736665720a01000000017f747b67bd3fe63c2a736739dfe40156d622347346e70f68f51c178a75ce55370195a68b1a05731b7014e580b4c67a506e0339a7fffeaded9f24eb2e7f78b96bdd900b9be8ca33e4552a9a619dc4fc5e4e3a9f74a4b0537c14a5a8007d62a5dc06"; let result = Buffer.from(DeployUtil.deployToBytes(deploy)).toString('hex'); assert.equal(result, expected); }); it('Is possible to chain deploys using dependencies', () => { const senderKey = Keys.Ed25519.new(); const recipientKey = Keys.Ed25519.new(); const networkName = 'dimension-test'; const paymentAmount = 10000000000000; const transferAmount = 10; const transferId = 35; let payment = DeployUtil.standardPayment(paymentAmount); let session = DeployUtil.ExecutableDeployItem.newTransfer( transferAmount, recipientKey.publicKey, undefined, transferId ); // Build first deploy. let firstDeployParams = new DeployUtil.DeployParams( senderKey.publicKey, networkName ); let firstDeploy = DeployUtil.makeDeploy(firstDeployParams, session, payment); // Build second deploy with the first one as a dependency. let gasPrice = 1; let ttl = 1800000; let dependencies = [firstDeploy.hash]; let secondDeployParams = new DeployUtil.DeployParams( senderKey.publicKey, networkName, gasPrice, ttl, dependencies ); let secondDeploy = DeployUtil.makeDeploy(secondDeployParams, session, payment); assert.deepEqual(secondDeploy.header.dependencies, [firstDeploy.hash]); }); });