UNPKG

@tangany/waas

Version:

node.js SDK for Tangany Wallet as a Service API

217 lines (192 loc) 9.12 kB
const { Waas } = require("../dist"); const { EthereumPublicNetwork } = require("../src/waas"); const { config } = require("dotenv"); const assert = require("assert"); const { checkEnvVars } = require("./helpers"); const { getRandomHex } = require("./helpers"); const { resolve } = require("path"); const util = require("util"); const path = resolve(process.cwd(), ".env"); config({ path }); checkEnvVars(); describe("WaaS sample Ethereum workflow", function () { const timeout = 160e3; this.timeout(timeout); this.slow(timeout / 3); const tokenWallet = process.env.E2E_WALLET; // Wallet with some Ether balance that owns the ERC20 token const tokenAddress = process.env.E2E_TOKEN; // mintable & burnable ERC20 token address deployed by the tokenWallet to Goerli const tokenAmount = "0.0032"; // Token amount used for transactions const etherAmount = "0.002"; // Ether amount used for transactions let tokenWalletAddress; // Token wallet address let createdWallet; // Random created wallet name let createdWalletAddress; // Created wallet address let txHash; // Tx hashes // Tangany-based smart contract ("Caller") used for testing here: // https://github.com/Tangany/truffle-blueprint/blob/master/contracts/Caller.sol const callerContract = "0x735fcc036022122082A6f870D6c02F5B3a38668B"; const api = new Waas({ ethereumNetwork: EthereumPublicNetwork.GOERLI, // All tests execute on the goerli testnet }, undefined, true); before(async function () { tokenWalletAddress = (await api.wallet(tokenWallet).eth().get()).address; }) it("should create a new wallet", async function () { const { security, created, version, wallet, updated } = await api.wallet().create(); assert.ok(security); assert.ok(created); assert.ok(version); assert.ok(wallet); assert.ok(updated); createdWallet = wallet; console.log(`created wallet ${createdWallet}`); }); it("should get the created wallet data", async function () { assert.ok(createdWallet, "cannot run without previous tests"); const { security, created, version, wallet, updated } = await api.wallet(createdWallet).get(); assert.ok(security); assert.ok(created); assert.ok(version); assert.ok(wallet); assert.ok(updated); console.log("wallet", { updated, wallet, version, created, security }); assert.strictEqual(wallet, createdWallet); }); it("should get the Ethereum specs for created wallet", async function () { assert.ok(createdWallet, "cannot run without previous tests"); const { address, balance, currency, nonce } = await api.wallet(createdWallet).eth().get(); assert.ok(address); assert.strictEqual(balance, "0"); assert.strictEqual(currency, "tETH"); assert.ok(typeof nonce === "number"); createdWalletAddress = address; console.log(`address for created wallet: ${createdWalletAddress}. Balance: ${balance}`); }); it("should sign payload with wallet", async function () { assert.ok(createdWallet, "cannot run without previous tests"); const payload = "messageToSign" const res = await api.wallet(createdWallet).eth().personalSign(payload); console.log(res); assert.ok(res.address); assert.ok(res.payloadHash); assert.ok(res.payload); assert.ok(res.payload == payload) assert.ok(res.signature); }); it("should interact with a smart contract using the universal contract endpoint", async function () { const request = await api.wallet(tokenWallet).eth().contract(tokenAddress).sendAsync({ function: "transfer(address,uint256)", inputs: [createdWalletAddress, "3200000000000000"] }); console.log(`asynchronous transaction request '${request.id}' started...`); await request.wait(35e5); const { output } = await request.get(); txHash = output.hash; console.log(output); assert.ok(output); }); it("should get the transaction status for the hash", async function () { assert.ok(txHash, "cannot run without previous tests"); const { blockNr, isError, data, confirmations, status } = await api.eth(txHash).get(); console.log("inital tx status", { blockNr, isError, data, confirmations, status }); assert.strictEqual(isError, false); assert.notStrictEqual(status, "unknown"); }); it("should wait for the transaction to get mined", async function () { assert.ok(txHash, "cannot run without previous tests"); const { isError, blockNr } = await api.eth(txHash).wait(timeout); assert.ok(typeof blockNr === "number"); console.log(`mined in blockNr ${blockNr}`); }); it("should get the new token balance for the new wallet", async function () { const { currency, balance } = await api.wallet(createdWallet).eth().erc20(tokenAddress).get(); assert.ok(currency); assert.strictEqual(balance, tokenAmount); console.log(`new token balance: ${balance}`); }); it("should estimate the transaction fee for a transaction", async function () { assert.ok(createdWalletAddress, "cannot run without previous tests"); const estimation = await api.wallet(tokenWallet).eth().estimateFee({ to: createdWalletAddress, amount: etherAmount }); console.log(`fee estimation: ${JSON.stringify(estimation, null, 2)}`); }) it("should send small amount of ether to new wallet", async function () { assert.ok(createdWalletAddress, "cannot run without previous tests"); const req = await api.wallet(tokenWallet).eth().sendAsync({ to: createdWalletAddress, amount: etherAmount }); console.log(`Wait for completion of request with id ${req.id}...`); await req.wait(35e5); const { output } = await req.get(); const hash = output.hash; console.log(`transaction made with txhash ${hash}. Waiting for the transaction to get mined...`); await api.eth(hash).wait(timeout); console.log(output); }); it("should estimate the transaction fee for a smart contract interaction", async function () { const estimation = await api.wallet(tokenWallet).eth().contract(tokenAddress).estimateFee({ function: "transfer(address,uint256)", inputs: [createdWalletAddress, "2500000000000000"] }); console.log(`fee estimation: ${JSON.stringify(estimation, null, 2)}`); }); it("should call a readonly smart contract function", async function(){ assert.ok(tokenWalletAddress, "cannot run without previous tests"); const contractResponse = await api.eth().contract(tokenAddress).call({ function: "balanceOf(address)", inputs: [tokenWalletAddress], outputs: ["uint256"] }); console.log(`Contract call result: ${JSON.stringify(contractResponse)}`); }) it("should call a readonly smart contract without arguments", async function () { const symbol = await api.eth().contract(tokenAddress).call("symbol", ["string"]); console.log(`Symbol of contract ${tokenAddress}: ${symbol[0].value}`); // Omit the second argument, because the default value ["uint256"] is suitable for totalSupply() const supply = await api.eth().contract(tokenAddress).call("totalSupply"); console.log(`Total supply of ${symbol[0].value}: ${supply[0].value}`); }); it("should call a readonly smart contract function on behalf of a wallet", async function () { assert.ok(tokenWalletAddress, "cannot run without previous tests"); assert.ok(createdWalletAddress, "cannot run without previous tests"); // balanceOf expects an address as first argument, which is set automatically in this overload const balance = await api.wallet(tokenWallet).eth().contract(tokenAddress).call("balanceOf"); console.log(`balanceOf(${tokenWalletAddress}): ${balance[0].value}`); // Since the allowance function expects several parameters, we use the overload with the configuration object const allowance = await api.wallet(tokenWallet).eth().contract(tokenAddress).call({ function: "allowance(address,address)", inputs: [tokenWalletAddress, createdWalletAddress], outputs: ["uint256"], }); console.log(`Result for allowance(${tokenWalletAddress}, ${createdWalletAddress}): ${JSON.stringify(allowance)}`); }); it("should call a smart contract function with nested array argument", async function () { const resultArr = await api.eth().contract(callerContract).call({ "function": "callFlattenAddressArray(address[][2])", "inputs": [ [ [ "0x0120000000000000000000000000000000000000", "0x0340000000000000000000000000000000000000" ], [ "0x1330000000000000000000000000000000000000", "0x1440000000000000000000000000000000000000", "0x1550000000000000000000000000000000000000" ] ] ], outputs: ["address[]"] }); const expected = [ "0x0120000000000000000000000000000000000000", "0x0340000000000000000000000000000000000000", "0x1330000000000000000000000000000000000000", "0x1440000000000000000000000000000000000000", "0x1550000000000000000000000000000000000000" ]; assert.deepStrictEqual(resultArr[0].value, expected); }); it("should delete the new wallet", async function () { const { recoveryId, scheduledPurgeDate } = await api.wallet(createdWallet).delete(); assert.ok(recoveryId); assert.ok(scheduledPurgeDate); console.log(`soft deleted wallet ${recoveryId} and scheduled for purging at ${scheduledPurgeDate}`); }); });