diff --git a/package-lock.json b/package-lock.json index acabfc36..6e0f7d1e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,9 +15,9 @@ "@tradetrust-tt/document-store": "^4.1.1", "@tradetrust-tt/token-registry": "^5.2.0", "@tradetrust-tt/tradetrust": "^6.10.0", - "@tradetrust-tt/tradetrust-config": "^1.19.0", - "@tradetrust-tt/tt-verify": "^9.5.0", - "@trustvc/trustvc": "^1.7.0", + "@tradetrust-tt/tradetrust-config": "^1.18.0", + "@tradetrust-tt/tt-verify": "^9.4.0", + "@trustvc/trustvc": "1.6.0-alpha.3", "ajv": "^8.4.0", "ajv-formats": "^2.1.0", "chalk": "^4.1.2", @@ -7395,9 +7395,8 @@ } }, "node_modules/@trustvc/trustvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@trustvc/trustvc/-/trustvc-1.7.0.tgz", - "integrity": "sha512-1spJLKIYyOCU87DiB/Kbsc0OghB6/SZXca+OmaFllrKEHxyT6rAJY2ihKBALIz3vifXY3Q94XZyDzjRxg4q7DQ==", + "version": "1.6.0-alpha.3", + "integrity": "sha512-Ng2ADFKKByAnZPDaNwM4V+15AvwrEaLNI8l5pSLKGUkx4tXMRV4tY9REbzY4sRtstZo4qL6Zda72M3i6teHg2A==", "dependencies": { "@tradetrust-tt/dnsprove": "^2.17.0", "@tradetrust-tt/ethers-aws-kms-signer": "^2.1.4", diff --git a/package.json b/package.json index ed68cb0c..151fa1c8 100644 --- a/package.json +++ b/package.json @@ -75,9 +75,9 @@ "@tradetrust-tt/document-store": "^4.1.1", "@tradetrust-tt/token-registry": "^5.2.0", "@tradetrust-tt/tradetrust": "^6.10.0", - "@tradetrust-tt/tradetrust-config": "^1.19.0", - "@tradetrust-tt/tt-verify": "^9.5.0", - "@trustvc/trustvc": "^1.7.0", + "@tradetrust-tt/tradetrust-config": "^1.18.0", + "@tradetrust-tt/tt-verify": "^9.4.0", + "@trustvc/trustvc": "1.6.0-alpha.3", "ajv": "^8.4.0", "ajv-formats": "^2.1.0", "chalk": "^4.1.2", diff --git a/src/implementations/token-registry/issue-astron.test.ts b/src/implementations/token-registry/issue-astron.test.ts index d33d1e29..56a115f2 100644 --- a/src/implementations/token-registry/issue-astron.test.ts +++ b/src/implementations/token-registry/issue-astron.test.ts @@ -1,11 +1,12 @@ -import { TradeTrustToken__factory } from "@tradetrust-tt/token-registry/contracts"; import { Wallet } from "ethers"; - import { TokenRegistryIssueCommand } from "../../commands/token-registry/token-registry-command.type"; import { addAddressPrefix } from "../../utils"; import { issueToTokenRegistry } from "./issue"; +import { mint } from "@trustvc/trustvc"; -jest.mock("@tradetrust-tt/token-registry/contracts"); +jest.mock("@trustvc/trustvc", () => ({ + mint: jest.fn(), +})); const deployParams: TokenRegistryIssueCommand = { beneficiary: "0xabcd", @@ -17,6 +18,16 @@ const deployParams: TokenRegistryIssueCommand = { dryRun: false, }; +const mockTransaction = { + transactionHash: "0x194bdcf15e", + to: "0x1234", + from: "0x5678", + transactionIndex: 0, + blockHash: "0xabcd", + logs: [], + events: [], +}; + describe("token-registry", () => { describe("issue", () => { // increase timeout because ethers is throttling @@ -34,33 +45,16 @@ describe("token-registry", () => { }) ) as jest.Mock ); - const mockedTradeTrustTokenFactory: jest.Mock = TradeTrustToken__factory as any; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore mock static method - const mockedConnectERC721: jest.Mock = mockedTradeTrustTokenFactory.connect; - const mockedIssue = jest.fn(); - const mockCallStaticSafeMint = jest.fn().mockResolvedValue(undefined); - - const mockTtErc721Contract = { - mint: mockedIssue, - callStatic: { - mint: mockCallStaticSafeMint, - }, - }; - - beforeAll(() => { - mockedIssue.mockReturnValue({ - hash: "hash", - wait: () => Promise.resolve({ transactionHash: "transactionHash" }), - }); - }); + const mockedMint = mint as jest.MockedFunction; beforeEach(() => { delete process.env.OA_PRIVATE_KEY; - mockedTradeTrustTokenFactory.mockClear(); - mockCallStaticSafeMint.mockClear(); - mockedConnectERC721.mockReset(); - mockedConnectERC721.mockResolvedValue(mockTtErc721Contract); + mockedMint.mockClear(); + mockedMint.mockResolvedValue({ + hash: "0x194bdcf15e", + blockNumber: 123, + wait: () => Promise.resolve(mockTransaction as any), + } as any); }); it("should pass in the correct params and return the deployed instance", async () => { @@ -70,32 +64,33 @@ describe("token-registry", () => { key: privateKey, }); - const passedSigner: Wallet = mockedConnectERC721.mock.calls[0][1]; - expect(passedSigner.privateKey).toBe(`0x${privateKey}`); - expect(mockedConnectERC721.mock.calls[0][0]).toEqual(deployParams.address); - expect(mockedIssue.mock.calls[0][0]).toEqual(deployParams.beneficiary); - expect(mockedIssue.mock.calls[0][1]).toEqual(deployParams.holder); - expect(mockedIssue.mock.calls[0][2]).toEqual(deployParams.tokenId); - expect(mockCallStaticSafeMint).toHaveBeenCalledTimes(1); - expect(instance).toStrictEqual({ transactionHash: "transactionHash" }); + expect(mockedMint).toHaveBeenCalledTimes(1); + const [contractOptions, signer, params] = mockedMint.mock.calls[0]; + expect(contractOptions.tokenRegistryAddress).toEqual(deployParams.address); + expect((signer as Wallet).privateKey).toBe(`0x${privateKey}`); + expect(params.beneficiaryAddress).toEqual(deployParams.beneficiary); + expect(params.holderAddress).toEqual(deployParams.holder); + expect(params.tokenId).toEqual(deployParams.tokenId); + expect(instance).toStrictEqual(mockTransaction); }); it("should accept tokenId without 0x prefix and return deployed instance", async () => { const privateKey = "0000000000000000000000000000000000000000000000000000000000000001"; + const tokenIdWithPrefix = addAddressPrefix("zyxw"); const instance = await issueToTokenRegistry({ ...deployParams, key: privateKey, - tokenId: addAddressPrefix("zyxw"), + tokenId: tokenIdWithPrefix, }); - const passedSigner: Wallet = mockedConnectERC721.mock.calls[0][1]; - expect(passedSigner.privateKey).toBe(`0x${privateKey}`); - expect(mockedConnectERC721.mock.calls[0][0]).toEqual(deployParams.address); - expect(mockedIssue.mock.calls[0][0]).toEqual(deployParams.beneficiary); - expect(mockedIssue.mock.calls[0][1]).toEqual(deployParams.holder); - expect(mockedIssue.mock.calls[0][2]).toEqual(deployParams.tokenId); - expect(mockCallStaticSafeMint).toHaveBeenCalledTimes(1); - expect(instance).toStrictEqual({ transactionHash: "transactionHash" }); + expect(mockedMint).toHaveBeenCalledTimes(1); + const [contractOptions, signer, params] = mockedMint.mock.calls[0]; + expect(contractOptions.tokenRegistryAddress).toEqual(deployParams.address); + expect((signer as Wallet).privateKey).toBe(`0x${privateKey}`); + expect(params.beneficiaryAddress).toEqual(deployParams.beneficiary); + expect(params.holderAddress).toEqual(deployParams.holder); + expect(params.tokenId).toEqual(tokenIdWithPrefix); + expect(instance).toStrictEqual(mockTransaction); }); it("should throw when keys are not found anywhere", async () => { @@ -106,9 +101,7 @@ describe("token-registry", () => { it("should allow errors to bubble up", async () => { process.env.OA_PRIVATE_KEY = "0000000000000000000000000000000000000000000000000000000000000002"; - mockedConnectERC721.mockImplementation(() => { - throw new Error("An Error"); - }); + mockedMint.mockRejectedValue(new Error("An Error")); await expect(issueToTokenRegistry(deployParams)).rejects.toThrow("An Error"); }); }); diff --git a/src/implementations/token-registry/issue-astrontestnet.test.ts b/src/implementations/token-registry/issue-astrontestnet.test.ts index 7e7bdad8..658e0584 100644 --- a/src/implementations/token-registry/issue-astrontestnet.test.ts +++ b/src/implementations/token-registry/issue-astrontestnet.test.ts @@ -1,11 +1,12 @@ -import { TradeTrustToken__factory } from "@tradetrust-tt/token-registry/contracts"; import { Wallet } from "ethers"; - import { TokenRegistryIssueCommand } from "../../commands/token-registry/token-registry-command.type"; import { addAddressPrefix } from "../../utils"; import { issueToTokenRegistry } from "./issue"; +import { mint } from "@trustvc/trustvc"; -jest.mock("@tradetrust-tt/token-registry/contracts"); +jest.mock("@trustvc/trustvc", () => ({ + mint: jest.fn(), +})); const deployParams: TokenRegistryIssueCommand = { beneficiary: "0xabcd", @@ -17,6 +18,16 @@ const deployParams: TokenRegistryIssueCommand = { dryRun: false, }; +const mockTransaction = { + transactionHash: "0x194bdcf15e", + to: "0x1234", + from: "0x5678", + transactionIndex: 0, + blockHash: "0xabcd", + logs: [], + events: [], +}; + describe("token-registry", () => { describe("issue", () => { // increase timeout because ethers is throttling @@ -34,33 +45,16 @@ describe("token-registry", () => { }) ) as jest.Mock ); - const mockedTradeTrustTokenFactory: jest.Mock = TradeTrustToken__factory as any; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore mock static method - const mockedConnectERC721: jest.Mock = mockedTradeTrustTokenFactory.connect; - const mockedIssue = jest.fn(); - const mockCallStaticSafeMint = jest.fn().mockResolvedValue(undefined); - - const mockTtErc721Contract = { - mint: mockedIssue, - callStatic: { - mint: mockCallStaticSafeMint, - }, - }; - - beforeAll(() => { - mockedIssue.mockReturnValue({ - hash: "hash", - wait: () => Promise.resolve({ transactionHash: "transactionHash" }), - }); - }); + const mockedMint = mint as jest.MockedFunction; beforeEach(() => { delete process.env.OA_PRIVATE_KEY; - mockedTradeTrustTokenFactory.mockClear(); - mockCallStaticSafeMint.mockClear(); - mockedConnectERC721.mockReset(); - mockedConnectERC721.mockResolvedValue(mockTtErc721Contract); + mockedMint.mockClear(); + mockedMint.mockResolvedValue({ + hash: "0x194bdcf15e", + blockNumber: 123, + wait: () => Promise.resolve(mockTransaction as any), + } as any); }); it("should pass in the correct params and return the deployed instance", async () => { @@ -70,32 +64,33 @@ describe("token-registry", () => { key: privateKey, }); - const passedSigner: Wallet = mockedConnectERC721.mock.calls[0][1]; - expect(passedSigner.privateKey).toBe(`0x${privateKey}`); - expect(mockedConnectERC721.mock.calls[0][0]).toEqual(deployParams.address); - expect(mockedIssue.mock.calls[0][0]).toEqual(deployParams.beneficiary); - expect(mockedIssue.mock.calls[0][1]).toEqual(deployParams.holder); - expect(mockedIssue.mock.calls[0][2]).toEqual(deployParams.tokenId); - expect(mockCallStaticSafeMint).toHaveBeenCalledTimes(1); - expect(instance).toStrictEqual({ transactionHash: "transactionHash" }); + expect(mockedMint).toHaveBeenCalledTimes(1); + const [contractOptions, signer, params] = mockedMint.mock.calls[0]; + expect(contractOptions.tokenRegistryAddress).toEqual(deployParams.address); + expect((signer as Wallet).privateKey).toBe(`0x${privateKey}`); + expect(params.beneficiaryAddress).toEqual(deployParams.beneficiary); + expect(params.holderAddress).toEqual(deployParams.holder); + expect(params.tokenId).toEqual(deployParams.tokenId); + expect(instance).toStrictEqual(mockTransaction); }); it("should accept tokenId without 0x prefix and return deployed instance", async () => { const privateKey = "0000000000000000000000000000000000000000000000000000000000000001"; + const tokenIdWithPrefix = addAddressPrefix("zyxw"); const instance = await issueToTokenRegistry({ ...deployParams, key: privateKey, - tokenId: addAddressPrefix("zyxw"), + tokenId: tokenIdWithPrefix, }); - const passedSigner: Wallet = mockedConnectERC721.mock.calls[0][1]; - expect(passedSigner.privateKey).toBe(`0x${privateKey}`); - expect(mockedConnectERC721.mock.calls[0][0]).toEqual(deployParams.address); - expect(mockedIssue.mock.calls[0][0]).toEqual(deployParams.beneficiary); - expect(mockedIssue.mock.calls[0][1]).toEqual(deployParams.holder); - expect(mockedIssue.mock.calls[0][2]).toEqual(deployParams.tokenId); - expect(mockCallStaticSafeMint).toHaveBeenCalledTimes(1); - expect(instance).toStrictEqual({ transactionHash: "transactionHash" }); + expect(mockedMint).toHaveBeenCalledTimes(1); + const [contractOptions, signer, params] = mockedMint.mock.calls[0]; + expect(contractOptions.tokenRegistryAddress).toEqual(deployParams.address); + expect((signer as Wallet).privateKey).toBe(`0x${privateKey}`); + expect(params.beneficiaryAddress).toEqual(deployParams.beneficiary); + expect(params.holderAddress).toEqual(deployParams.holder); + expect(params.tokenId).toEqual(tokenIdWithPrefix); + expect(instance).toStrictEqual(mockTransaction); }); it("should throw when keys are not found anywhere", async () => { @@ -106,9 +101,7 @@ describe("token-registry", () => { it("should allow errors to bubble up", async () => { process.env.OA_PRIVATE_KEY = "0000000000000000000000000000000000000000000000000000000000000002"; - mockedConnectERC721.mockImplementation(() => { - throw new Error("An Error"); - }); + mockedMint.mockRejectedValue(new Error("An Error")); await expect(issueToTokenRegistry(deployParams)).rejects.toThrow("An Error"); }); }); diff --git a/src/implementations/token-registry/issue.test.ts b/src/implementations/token-registry/issue.test.ts index 36015cd0..d2ccc268 100644 --- a/src/implementations/token-registry/issue.test.ts +++ b/src/implementations/token-registry/issue.test.ts @@ -1,11 +1,12 @@ -import { TradeTrustToken__factory } from "@tradetrust-tt/token-registry/contracts"; import { Wallet } from "ethers"; - import { TokenRegistryIssueCommand } from "../../commands/token-registry/token-registry-command.type"; import { addAddressPrefix } from "../../utils"; import { issueToTokenRegistry } from "./issue"; +import { mint } from "@trustvc/trustvc"; -jest.mock("@tradetrust-tt/token-registry/contracts"); +jest.mock("@trustvc/trustvc", () => ({ + mint: jest.fn(), +})); const deployParams: TokenRegistryIssueCommand = { beneficiary: "0xabcd", @@ -19,35 +20,31 @@ const deployParams: TokenRegistryIssueCommand = { dryRun: false, }; +const mockTransaction = { + transactionHash: "0x194bdcf15e", + to: "0x1234", + from: "0x5678", + transactionIndex: 0, + blockHash: "0xabcd", + logs: [], + events: [], +}; + describe("token-registry", () => { describe("issue", () => { jest.setTimeout(30000); - const mockedTradeTrustTokenFactory: jest.Mock = TradeTrustToken__factory as any; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore mock static method - const mockedConnectERC721: jest.Mock = mockedTradeTrustTokenFactory.connect; - const mockedIssue = jest.fn(); - const mockCallStaticSafeMint = jest.fn().mockResolvedValue(undefined); - - const mockTtErc721Contract = { - mint: mockedIssue, - callStatic: { - mint: mockCallStaticSafeMint, - }, - }; + const mockedMint = mint as jest.MockedFunction; beforeEach(() => { delete process.env.OA_PRIVATE_KEY; - mockedTradeTrustTokenFactory.mockClear(); - mockCallStaticSafeMint.mockClear(); - mockedConnectERC721.mockReset(); - mockedConnectERC721.mockResolvedValue(mockTtErc721Contract); - - mockedIssue.mockReturnValue({ - hash: "hash", - wait: () => Promise.resolve({ transactionHash: "transactionHash" }), - }); + mockedMint.mockClear(); + mockedMint.mockResolvedValue({ + hash: "0x194bdcf15e", + blockNumber: 123, + wait: () => Promise.resolve(mockTransaction as any), + } as any); }); + it("should pass in the correct params and return the deployed instance", async () => { const privateKey = "0000000000000000000000000000000000000000000000000000000000000001"; const instance = await issueToTokenRegistry({ @@ -55,32 +52,41 @@ describe("token-registry", () => { key: privateKey, }); - const passedSigner: Wallet = mockedConnectERC721.mock.calls[0][1]; - expect(passedSigner.privateKey).toBe(`0x${privateKey}`); - expect(mockedConnectERC721.mock.calls[0][0]).toEqual(deployParams.address); - expect(mockedIssue.mock.calls[0][0]).toEqual(deployParams.beneficiary); - expect(mockedIssue.mock.calls[0][1]).toEqual(deployParams.holder); - expect(mockedIssue.mock.calls[0][2]).toEqual(deployParams.tokenId); - expect(mockCallStaticSafeMint).toHaveBeenCalledTimes(1); - expect(instance).toStrictEqual({ transactionHash: "transactionHash" }); + expect(mockedMint).toHaveBeenCalledTimes(1); + const [contractOptions, signer, params, options] = mockedMint.mock.calls[0]; + expect(contractOptions.tokenRegistryAddress).toEqual(deployParams.address); + expect((signer as Wallet).privateKey).toBe(`0x${privateKey}`); + + expect(params.beneficiaryAddress).toEqual(deployParams.beneficiary); + expect(params.holderAddress).toEqual(deployParams.holder); + expect(params.tokenId).toEqual(deployParams.tokenId); + expect(params.remarks).toEqual(deployParams.remark); + + expect(options.id).toEqual(deployParams.encryptionKey); + expect(instance).toStrictEqual(mockTransaction); }); it("should accept tokenId without 0x prefix and return deployed instance", async () => { const privateKey = "0000000000000000000000000000000000000000000000000000000000000001"; + const tokenIdWithPrefix = addAddressPrefix("zyxw"); const instance = await issueToTokenRegistry({ ...deployParams, key: privateKey, - tokenId: addAddressPrefix("zyxw"), + tokenId: tokenIdWithPrefix, }); - const passedSigner: Wallet = mockedConnectERC721.mock.calls[0][1]; - expect(passedSigner.privateKey).toBe(`0x${privateKey}`); - expect(mockedConnectERC721.mock.calls[0][0]).toEqual(deployParams.address); - expect(mockedIssue.mock.calls[0][0]).toEqual(deployParams.beneficiary); - expect(mockedIssue.mock.calls[0][1]).toEqual(deployParams.holder); - expect(mockedIssue.mock.calls[0][2]).toEqual(deployParams.tokenId); - expect(mockCallStaticSafeMint).toHaveBeenCalledTimes(1); - expect(instance).toStrictEqual({ transactionHash: "transactionHash" }); + expect(mockedMint).toHaveBeenCalledTimes(1); + const [contractOptions, signer, params, options] = mockedMint.mock.calls[0]; + expect(contractOptions.tokenRegistryAddress).toEqual(deployParams.address); + expect((signer as Wallet).privateKey).toBe(`0x${privateKey}`); + + expect(params.beneficiaryAddress).toEqual(deployParams.beneficiary); + expect(params.holderAddress).toEqual(deployParams.holder); + expect(params.tokenId).toEqual(tokenIdWithPrefix); + expect(params.remarks).toEqual(deployParams.remark); + + expect(options.id).toEqual(deployParams.encryptionKey); + expect(instance).toStrictEqual(mockTransaction); }); it("should throw when keys are not found anywhere", async () => { @@ -91,9 +97,7 @@ describe("token-registry", () => { it("should allow errors to bubble up", async () => { process.env.OA_PRIVATE_KEY = "0000000000000000000000000000000000000000000000000000000000000002"; - mockedConnectERC721.mockImplementation(() => { - throw new Error("An Error"); - }); + mockedMint.mockRejectedValue(new Error("An Error")); await expect(issueToTokenRegistry(deployParams)).rejects.toThrow("An Error"); }); }); diff --git a/src/implementations/token-registry/issue.ts b/src/implementations/token-registry/issue.ts index 6b8b9b93..be41f54f 100644 --- a/src/implementations/token-registry/issue.ts +++ b/src/implementations/token-registry/issue.ts @@ -1,12 +1,11 @@ -import { TradeTrustToken, TradeTrustToken__factory } from "@tradetrust-tt/token-registry/contracts"; import signale from "signale"; import { getLogger } from "../../logger"; import { getWalletOrSigner } from "../utils/wallet"; import { TokenRegistryIssueCommand } from "../../commands/token-registry/token-registry-command.type"; -import { dryRunMode } from "../utils/dryRun"; import { TransactionReceipt } from "@ethersproject/providers"; import { canEstimateGasPrice, getGasFees } from "../../utils"; -import { validateAndEncryptRemark } from "../title-escrow/helpers"; +import { BigNumber } from "ethers"; +import { mint } from "@trustvc/trustvc"; const { trace } = getLogger("token-registry:issue"); @@ -22,30 +21,30 @@ export const issueToTokenRegistry = async ({ ...rest }: TokenRegistryIssueCommand): Promise => { const wallet = await getWalletOrSigner({ network, ...rest }); - const tokenRegistry: TradeTrustToken = await TradeTrustToken__factory.connect(address, wallet); - const encryptedRemark = validateAndEncryptRemark(remark, encryptionKey); + let transactionOptions: { maxFeePerGas?: BigNumber; maxPriorityFeePerGas?: BigNumber } = {}; + if (dryRun) { - await dryRunMode({ - estimatedGas: await tokenRegistry.estimateGas.mint(beneficiary, holder, tokenId, encryptedRemark), - network, - }); + console.log("🔧 Dry run mode is currently undergoing upgrades and will be available soon."); process.exit(0); } - let transaction; if (canEstimateGasPrice(network)) { const gasFees = await getGasFees({ provider: wallet.provider, ...rest }); trace(`Gas maxFeePerGas: ${gasFees.maxFeePerGas}`); trace(`Gas maxPriorityFeePerGas: ${gasFees.maxPriorityFeePerGas}`); - await tokenRegistry.callStatic.mint(beneficiary, holder, tokenId, encryptedRemark); - signale.await(`Sending transaction to pool`); - transaction = await tokenRegistry.mint(beneficiary, holder, tokenId, encryptedRemark, { ...gasFees }); - } else { - await tokenRegistry.callStatic.mint(beneficiary, holder, tokenId, encryptedRemark); - signale.await(`Sending transaction to pool`); - transaction = await tokenRegistry.mint(beneficiary, holder, tokenId, encryptedRemark); + transactionOptions = { + maxFeePerGas: gasFees.maxFeePerGas as BigNumber, + maxPriorityFeePerGas: gasFees.maxPriorityFeePerGas as BigNumber, + }; } + const transaction = await mint( + { tokenRegistryAddress: address }, + wallet, + { beneficiaryAddress: beneficiary, holderAddress: holder, tokenId, remarks: remark }, + { id: encryptionKey, ...transactionOptions } + ); + trace(`Tx hash: ${transaction.hash}`); trace(`Block Number: ${transaction.blockNumber}`); signale.await(`Waiting for transaction ${transaction.hash} to be mined`);