From a7b6498bd611ae7b59dcb8cda28134ab31defe02 Mon Sep 17 00:00:00 2001 From: Jakub Zajkowski Date: Fri, 21 Jun 2024 12:03:30 +0200 Subject: [PATCH 1/4] rebasing --- e2e/services/CasperServiceByJsonRPC.test.ts | 268 ++++++++++++++++---- e2e/services/cep18.wasm | Bin 0 -> 325067 bytes run_e2e_locally.sh | 2 +- src/lib/Contracts.ts | 24 +- src/lib/PricingMode.ts | 5 +- src/lib/TransactionEntryPoint.test.ts | 13 + src/lib/TransactionEntryPoint.ts | 23 +- src/lib/TransactionInvocationTarget.ts | 7 + src/lib/TransactionTarget.ts | 21 ++ src/lib/TransactionUtil.ts | 41 +-- src/services/CasperServiceByJsonRPC.ts | 48 ++-- 11 files changed, 341 insertions(+), 111 deletions(-) create mode 100755 e2e/services/cep18.wasm diff --git a/e2e/services/CasperServiceByJsonRPC.test.ts b/e2e/services/CasperServiceByJsonRPC.test.ts index e837a267c..d59dd81cc 100644 --- a/e2e/services/CasperServiceByJsonRPC.test.ts +++ b/e2e/services/CasperServiceByJsonRPC.test.ts @@ -24,18 +24,51 @@ import { TransactionUtil, CLU64, CLU64Type, - encodeBase16 + encodeBase16, + decodeBase16, + TransactionRuntime } from '../../src/index'; import { sleep } from './utils'; import { Contract } from '../../src/lib/Contracts'; import { FAUCET_PRIV_KEY, NETWORK_NAME, NODE_URL } from '../config'; -import { PricingMode } from '../../src/lib/TransactionUtil'; -import { Native } from '../../src/lib/TransactionTarget'; -import { Transfer } from '../../src/lib/TransactionEntryPoint'; -import { Standard } from '../../src/lib/TransactionScheduling'; +import { + PricingMode, + TransactionCategoryInstallUpgrade, + TransactionCategoryLarge, + TransactionCategoryMint, + TransactionCategorySmall, + makeV1Transaction +} from '../../src/lib/TransactionUtil'; +import { + Native, + Session, + Stored, + TransactionSessionKind, + TransactionTarget +} from '../../src/lib/TransactionTarget'; +import { + Call, + Custom, + TransactionEntryPoint, + Transfer, + WithdrawBid +} from '../../src/lib/TransactionEntryPoint'; +import { + Standard, + TransactionScheduling +} from '../../src/lib/TransactionScheduling'; import { InitiatorAddr } from '../../src/lib/InitiatorAddr'; import { Some } from 'ts-results'; +import { DEFAULT_DEPLOY_TTL } from '../../src/constants'; +import { + ByPackageHashJson, + TransactionInvocationTarget +} from '../../src/lib/TransactionInvocationTarget'; +import { + undefinedSafeByteArrayJsonDeserializer, + undefinedSafeByteArrayJsonSerializer +} from '../../src/lib/Common'; config(); @@ -286,7 +319,8 @@ describe('CasperServiceByJsonRPC', () => { runtimeArgs, transactionTarget, transactionEntryPoint, - transactionScheduling + transactionScheduling, + TransactionCategoryMint ); const signedTransaction = TransactionUtil.signTransaction( @@ -401,33 +435,34 @@ describe('CasperServiceByJsonRPC', () => { assert.exists(named_key); }); - //TODO we need a new wasm that works with 2.0 - xit('should deploy wasm over rpc', async () => { + it('CEP18 should work deployed via "account_put_deploy"', async () => { const casperClient = new CasperClient(NODE_URL); - const erc20 = new Contract(casperClient); - const wasmPath = path.resolve(__dirname, './contract.wasm'); + const cep18 = new Contract(casperClient); + const wasmPath = path.resolve(__dirname, './cep18.wasm'); const wasm = new Uint8Array(fs.readFileSync(wasmPath, null).buffer); + let id = Date.now(); - const tokenName = 'TEST'; - const tokenSymbol = 'TST'; + const tokenName = 'TEST-' + id; + const tokenSymbol = 'TST-' + id; const tokenDecimals = 8; - const tokenTotlaSupply = 500_000_000_000; + const tokenTotalSupply = 500_000; - const args = RuntimeArgs.fromMap({ - message: CLValueBuilder.string(tokenName), + const runtimeArgs = RuntimeArgs.fromMap({ + name: CLValueBuilder.string(tokenName), symbol: CLValueBuilder.string(tokenSymbol), decimals: CLValueBuilder.u8(tokenDecimals), - total_supply: CLValueBuilder.u256(tokenTotlaSupply) + total_supply: CLValueBuilder.u256(tokenTotalSupply), + events_mode: CLValueBuilder.u8(0) }); - const signedDeploy = erc20.install( + + const signedDeploy = cep18.install( wasm, - args, - '200000000000', + runtimeArgs, + '50000000000', faucetKey.publicKey, NETWORK_NAME, [faucetKey] ); - await client.deploy(signedDeploy); await sleep(2500); @@ -439,50 +474,39 @@ describe('CasperServiceByJsonRPC', () => { }; const { AddressableEntity } = await client.getEntity(entity_identifier); const contractHash = AddressableEntity!.named_keys.find((i: NamedKey) => { - return i.name === 'erc20_token_contract'; + return i.name === 'cep18_contract_hash_' + tokenName; })?.key; assert.exists(contractHash); - erc20.setContractHash(contractHash!); - - const fetchedTokenName = await erc20.queryContractData(['name']); - const fetchedTokenSymbol = await erc20.queryContractData(['symbol']); - const fetchedTokenDecimals: BigNumber = await erc20.queryContractData([ + cep18.setContractHash(contractHash!); + cep18.setContractName(`cep18_contract_hash_${tokenName}`); + const fetchedTokenName = await cep18.queryContractData(['name']); + const fetchedTokenSymbol = await cep18.queryContractData(['symbol']); + const fetchedTokenDecimals: BigNumber = await cep18.queryContractData([ 'decimals' ]); - const fetchedTokenTotalSupply: BigNumber = await erc20.queryContractData([ + const fetchedTokenTotalSupply: BigNumber = await cep18.queryContractData([ 'total_supply' ]); - const balanceOf = async (erc20: Contract, owner: CLKeyParameters) => { - const balanceKey = Buffer.from( - CLValueParsers.toBytes(CLValueBuilder.key(owner)).unwrap() - ).toString('base64'); - const balance: BigNumber = ( - await erc20.queryContractDictionary('balances', balanceKey) - ).value(); - return balance; - }; - - const balanceOfFaucet = await balanceOf(erc20, faucetKey.publicKey); + const balanceOfFaucet = await balanceOf(cep18, faucetKey.publicKey); assert.equal(tokenName, fetchedTokenName); assert.equal(tokenSymbol, fetchedTokenSymbol); assert.equal(tokenDecimals, fetchedTokenDecimals.toNumber()); - assert.equal(tokenTotlaSupply, fetchedTokenTotalSupply.toNumber()); - assert.equal(balanceOfFaucet.toNumber(), tokenTotlaSupply); + assert.equal(tokenTotalSupply, fetchedTokenTotalSupply.toNumber()); + assert.equal(balanceOfFaucet.toNumber(), tokenTotalSupply); // Test `callEntrypoint` method: Transfter token const recipient = Ed25519.new().publicKey; const transferAmount = 2_000; - const transferArgs = RuntimeArgs.fromMap({ recipient: CLValueBuilder.key(recipient), amount: CLValueBuilder.u256(2_000) }); - const transferDeploy = erc20.callEntrypoint( + const transferDeploy = cep18.callEntrypoint( 'transfer', transferArgs, faucetKey.publicKey, @@ -490,15 +514,154 @@ describe('CasperServiceByJsonRPC', () => { '2500000000', [faucetKey] ); - const { deploy_hash } = await client.deploy(transferDeploy); + await sleep(2500); result = await client.waitForDeploy(transferDeploy, 100000); assert.equal(result.deploy.hash, deploy_hash); - expect(result.deploy.session).to.have.property('StoredContractByHash'); - // expect(result.execution_results[0].result).to.have.property('Success'); + expect(result.deploy.session).to.have.property('StoredContractByName'); + expect(result.execution_info!.execution_result!).to.have.property( + 'Version2' + ); + let amorphicExecutionResult: any = result.execution_info!.execution_result!; + if (amorphicExecutionResult['Version2']) { + expect(amorphicExecutionResult['Version2'].error_message).to.be.null; + } + const balanceOfRecipient = await balanceOf(cep18, recipient); + assert.equal(balanceOfRecipient.toNumber(), transferAmount); + }); + + it('CEP18 should work deployed via "account_put_transaction"', async () => { + const casperClient = new CasperClient(NODE_URL); + const cep18 = new Contract(casperClient); + const wasmPath = path.resolve(__dirname, './cep18.wasm'); + const wasm = new Uint8Array(fs.readFileSync(wasmPath, null).buffer); + const paymentAmount = 10000000000; + let id = Date.now(); + + const tokenName = 'TEST-' + id; + const tokenSymbol = 'TST-' + id; + const tokenDecimals = 8; + const tokenTotalSupply = 500_000; + const runtimeArgs = RuntimeArgs.fromMap({ + name: CLValueBuilder.string(tokenName), + symbol: CLValueBuilder.string(tokenSymbol), + decimals: CLValueBuilder.u8(tokenDecimals), + total_supply: CLValueBuilder.u256(tokenTotalSupply), + events_mode: CLValueBuilder.u8(0), + amount: CLValueBuilder.u512(paymentAmount) + }); + const params = new TransactionUtil.Version1Params( + InitiatorAddr.fromPublicKey(faucetKey.publicKey), + Date.now(), + DEFAULT_DEPLOY_TTL, + NETWORK_NAME, + PricingMode.fromFixed(3) + ); + const transaction = makeV1Transaction( + params, + runtimeArgs, + Session.build( + TransactionSessionKind.Installer, + wasm, + TransactionRuntime.VmCasperV1 + ), + new Call(), + new Standard(), + TransactionCategoryInstallUpgrade + ); + const signedTransaction = transaction.sign([faucetKey]); + await client.transaction(signedTransaction); + + await sleep(2500); + + let result = await client.waitForTransaction(signedTransaction, 100000); + + let entity_identifier = { + AccountHash: faucetKey.publicKey.toAccountHashStr() + }; + const { AddressableEntity } = await client.getEntity(entity_identifier); + const contractHash = AddressableEntity!.named_keys.find((i: NamedKey) => { + return i.name === 'cep18_contract_hash_' + tokenName; + })?.key; + + assert.exists(contractHash); + + cep18.setContractHash(contractHash!); + cep18.setContractName(`cep18_contract_hash_${tokenName}`); + const fetchedTokenName = await cep18.queryContractData(['name']); + const fetchedTokenSymbol = await cep18.queryContractData(['symbol']); + const fetchedTokenDecimals: BigNumber = await cep18.queryContractData([ + 'decimals' + ]); + const fetchedTokenTotalSupply: BigNumber = await cep18.queryContractData([ + 'total_supply' + ]); + + const balanceOfFaucet = await balanceOf(cep18, faucetKey.publicKey); + + assert.equal(tokenName, fetchedTokenName); + assert.equal(tokenSymbol, fetchedTokenSymbol); + assert.equal(tokenDecimals, fetchedTokenDecimals.toNumber()); + assert.equal(tokenTotalSupply, fetchedTokenTotalSupply.toNumber()); + assert.equal(balanceOfFaucet.toNumber(), tokenTotalSupply); + + // Test `callEntrypoint` method: Transfter token + const recipient = Ed25519.new().publicKey; + const transferAmount = 2_000; + const transferArgs = RuntimeArgs.fromMap({ + recipient: CLValueBuilder.key(recipient), + amount: CLValueBuilder.u256(2_000) + }); + + const runEndpointParams = new TransactionUtil.Version1Params( + InitiatorAddr.fromPublicKey(faucetKey.publicKey), + Date.now(), + DEFAULT_DEPLOY_TTL, + NETWORK_NAME, + PricingMode.fromFixed(3) + ); + const byHash = new TransactionInvocationTarget(); + const contractName = `cep18_contract_hash_${tokenName}`; + byHash.ByName = contractName; + const runEndpointTransaction = makeV1Transaction( + runEndpointParams, + transferArgs, + Stored.build(byHash, TransactionRuntime.VmCasperV1), + Custom.build('transfer'), + new Standard(), + TransactionCategoryLarge + ); - const balanceOfRecipient = await balanceOf(erc20, recipient); + const signedRunEndpointTransaction = runEndpointTransaction.sign([ + faucetKey + ]); + const { transaction_hash } = await client.transaction( + signedRunEndpointTransaction + ); + await sleep(2500); + const transferResult = await client.waitForTransaction( + signedRunEndpointTransaction, + 100000 + ); + assert.equal( + transferResult.transaction.Version1.hash, + transaction_hash.Version1! + ); + + expect( + transferResult.transaction.Version1.body.target.Stored.id + ).to.have.property('ByName'); + expect(transferResult.execution_info!.execution_result!).to.have.property( + 'Version2' + ); + let amorphicExecutionResult: any = transferResult.execution_info! + .execution_result!; + if (amorphicExecutionResult['Version2']) { + expect(amorphicExecutionResult['Version2'].error_message).to.be.null; + } + + const balanceOfRecipient = await balanceOf(cep18, recipient); assert.equal(balanceOfRecipient.toNumber(), transferAmount); }); @@ -552,3 +715,16 @@ describe('CasperServiceByJsonRPC', () => { // TODO xit('speculative_exec'); }); + +async function balanceOf( + erc20: Contract, + owner: CLKeyParameters +): Promise { + const balanceKey = Buffer.from( + CLValueParsers.toBytes(CLValueBuilder.key(owner)).unwrap() + ).toString('base64'); + const balance: BigNumber = ( + await erc20.queryContractDictionary('balances', balanceKey) + ).value(); + return balance; +} diff --git a/e2e/services/cep18.wasm b/e2e/services/cep18.wasm new file mode 100755 index 0000000000000000000000000000000000000000..580b1cf31541edeac53a5cad564762db6526008a GIT binary patch literal 325067 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