diff --git a/examples/developer-controlled-wallet/index.ts b/examples/developer-controlled-wallet/index.ts index 0c53e4b..35b85e7 100644 --- a/examples/developer-controlled-wallet/index.ts +++ b/examples/developer-controlled-wallet/index.ts @@ -46,8 +46,8 @@ async function main() { // Get Cardano wallet const { cardanoWallet: cardano } = await sdk.wallet.getWallet(info.id, "cardano"); - const addresses = cardano!.getAddresses(); - console.log("Cardano base address:", addresses.baseAddressBech32); + const cardanoAddress = await cardano!.getChangeAddressBech32(); + console.log("Cardano base address:", cardanoAddress); // Get Spark wallet info const sparkWalletInfo = await sdk.wallet.sparkIssuer.getWallet(info.id); diff --git a/examples/nextjs/app/page.tsx b/examples/nextjs/app/page.tsx index 56d935f..5093287 100644 --- a/examples/nextjs/app/page.tsx +++ b/examples/nextjs/app/page.tsx @@ -48,7 +48,7 @@ export default function Home() { const user = web3Wallet.getUser(); const cardanoAddress = - (await web3Wallet.cardano.getChangeAddress()) || ""; + (await web3Wallet.cardano.getChangeAddressBech32()) || ""; const bitcoinAddresses = await web3Wallet.bitcoin.getAddresses(); const bitcoinAddress = bitcoinAddresses[0]?.address || ""; const sparkAddressInfo = web3Wallet.spark.getAddress(); diff --git a/examples/react-native/App.tsx b/examples/react-native/App.tsx index 5dd9777..9184f4e 100644 --- a/examples/react-native/App.tsx +++ b/examples/react-native/App.tsx @@ -64,7 +64,7 @@ export default function App() { const user = web3Wallet.getUser(); const cardanoAddress = - (await web3Wallet.cardano.getChangeAddress()) || ""; + (await web3Wallet.cardano.getChangeAddressBech32()) || ""; const bitcoinAddresses = await web3Wallet.bitcoin.getAddresses(); const bitcoinAddress = bitcoinAddresses[0]?.address || ""; const sparkAddressInfo = web3Wallet.spark.getAddress(); diff --git a/examples/third-party-auth/app/page.tsx b/examples/third-party-auth/app/page.tsx index 3a7dd7b..7d6a57f 100644 --- a/examples/third-party-auth/app/page.tsx +++ b/examples/third-party-auth/app/page.tsx @@ -50,7 +50,7 @@ export default function Home() { refreshToken: token as string, }); - console.log(await wallet.cardano.getChangeAddress()); + console.log(await wallet.cardano.getChangeAddressBech32()); }} > Auto Sign In With Token{" "} diff --git a/package.json b/package.json index decd12d..523aeef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@utxos/sdk", - "version": "0.1.5", + "version": "0.2.0", "description": "UTXOS SDK - Web3 infrastructure platform for UTXO blockchains", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -66,7 +66,7 @@ "@meshsdk/common": "1.9.0-beta.89", "@meshsdk/core-cst": "1.9.0-beta.89", "@meshsdk/transaction": "1.9.0-beta.89", - "@meshsdk/wallet": "1.9.0-beta.89", + "@meshsdk/wallet": "2.0.0-beta.5", "@peculiar/webcrypto": "^1.5.0", "axios": "^1.8.3", "base32-encoding": "^1.0.0", diff --git a/src/functions/client/derive-wallet.test.ts b/src/functions/client/derive-wallet.test.ts index f7c2b89..c15a42b 100644 --- a/src/functions/client/derive-wallet.test.ts +++ b/src/functions/client/derive-wallet.test.ts @@ -3,11 +3,14 @@ import { encryptWithCipher } from "../crypto"; import { spiltKeyIntoShards } from "../key-shard"; // Mock external wallet SDKs +const mockCardanoWalletInstance = { + getUsedAddressesBech32: jest.fn().mockResolvedValue(["addr_test1..."]), +}; + jest.mock("@meshsdk/wallet", () => ({ - MeshWallet: jest.fn().mockImplementation(() => ({ - init: jest.fn().mockResolvedValue(undefined), - getUsedAddresses: jest.fn().mockResolvedValue(["addr_test1..."]), - })), + MeshCardanoHeadlessWallet: { + fromMnemonic: jest.fn().mockResolvedValue(mockCardanoWalletInstance), + }, })); jest.mock("@meshsdk/bitcoin", () => ({ @@ -28,7 +31,7 @@ jest.mock("@buildonspark/spark-sdk", () => ({ // Import after mocks import { clientDeriveWallet } from "./derive-wallet"; -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { EmbeddedWallet } from "@meshsdk/bitcoin"; import { SparkWallet } from "@buildonspark/spark-sdk"; @@ -122,7 +125,7 @@ describe("clientDeriveWallet", () => { expect(EmbeddedWallet).toHaveBeenCalledWith( expect.objectContaining({ network: "Testnet" }), ); - expect(MeshWallet).toHaveBeenCalledWith( + expect(MeshCardanoHeadlessWallet.fromMnemonic).toHaveBeenCalledWith( expect.objectContaining({ networkId: 0 }), ); expect(SparkWallet.initialize).toHaveBeenCalledWith( @@ -146,7 +149,7 @@ describe("clientDeriveWallet", () => { expect(EmbeddedWallet).toHaveBeenCalledWith( expect.objectContaining({ network: "Mainnet" }), ); - expect(MeshWallet).toHaveBeenCalledWith( + expect(MeshCardanoHeadlessWallet.fromMnemonic).toHaveBeenCalledWith( expect.objectContaining({ networkId: 1 }), ); expect(SparkWallet.initialize).toHaveBeenCalledWith( @@ -241,24 +244,6 @@ describe("clientDeriveWallet", () => { expect(result.key).toBe(testMnemonic); }); - it("initializes cardano wallet", async () => { - const shards = await spiltKeyIntoShards(testMnemonic); - const deviceKey = await deriveKeyFromPassword("device-password"); - - const encryptedDeviceShard = await encryptWithCipher({ - data: shards[0]!, - key: deviceKey, - }); - - const result = await clientDeriveWallet( - encryptedDeviceShard, - deviceKey, - shards[1]!, - 0, - ); - - expect(result.cardanoWallet.init).toHaveBeenCalled(); - }); }); describe("clientDeriveWallet with 24-word mnemonic", () => { diff --git a/src/functions/client/derive-wallet.ts b/src/functions/client/derive-wallet.ts index 152bd92..62a2900 100644 --- a/src/functions/client/derive-wallet.ts +++ b/src/functions/client/derive-wallet.ts @@ -1,4 +1,5 @@ import { IBitcoinProvider } from "@meshsdk/bitcoin"; +import { IFetcher } from "@meshsdk/common"; import { decryptWithCipher } from "../crypto"; import { combineShardsBuildWallet } from "../key-shard"; @@ -8,6 +9,7 @@ export async function clientDeriveWallet( custodialShard: string, networkId: 0 | 1, bitcoinProvider?: IBitcoinProvider, + fetcher?: IFetcher, ) { const keyShare1 = await decryptWithCipher({ encryptedDataJSON: encryptedKeyShard, @@ -21,6 +23,7 @@ export async function clientDeriveWallet( keyShare1, keyShare2, bitcoinProvider, + fetcher, ); return { bitcoinWallet, cardanoWallet, sparkWallet, key }; diff --git a/src/functions/client/generate-wallet.test.ts b/src/functions/client/generate-wallet.test.ts index 6fde73d..bac8c84 100644 --- a/src/functions/client/generate-wallet.test.ts +++ b/src/functions/client/generate-wallet.test.ts @@ -1,14 +1,16 @@ import { crypto } from "../crypto"; // Mock external wallet SDKs +const mockCardanoWalletInstance = { + getChangeAddressBech32: jest.fn().mockResolvedValue( + "addr_test1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwq2ytjqp", + ), +}; + jest.mock("@meshsdk/wallet", () => ({ - MeshWallet: jest.fn().mockImplementation(() => ({ - init: jest.fn().mockResolvedValue(undefined), - getAddresses: jest.fn().mockResolvedValue({ - baseAddressBech32: - "addr_test1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwq2ytjqp", - }), - })), + MeshCardanoHeadlessWallet: { + fromMnemonic: jest.fn().mockResolvedValue(mockCardanoWalletInstance), + }, })); jest.mock("@meshsdk/common", () => ({ @@ -47,7 +49,7 @@ jest.mock("@buildonspark/spark-sdk", () => ({ // Import after mocks import { clientGenerateWallet } from "./generate-wallet"; import { generateMnemonic } from "@meshsdk/common"; -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { EmbeddedWallet } from "@meshsdk/bitcoin"; import { SparkWallet } from "@buildonspark/spark-sdk"; import { decryptWithCipher } from "../crypto"; @@ -204,13 +206,13 @@ describe("clientGenerateWallet", () => { ); }); - it("creates MeshWallet with networkId 1", async () => { + it("creates MeshCardanoHeadlessWallet with networkId 1", async () => { const deviceKey = await deriveKeyFromPassword("device-password"); const recoveryKey = await deriveKeyFromPassword("recovery-password"); await clientGenerateWallet(deviceKey, recoveryKey); - expect(MeshWallet).toHaveBeenCalledWith( + expect(MeshCardanoHeadlessWallet.fromMnemonic).toHaveBeenCalledWith( expect.objectContaining({ networkId: 1 }), ); }); diff --git a/src/functions/client/generate-wallet.ts b/src/functions/client/generate-wallet.ts index bf3e04a..60acf5e 100644 --- a/src/functions/client/generate-wallet.ts +++ b/src/functions/client/generate-wallet.ts @@ -1,4 +1,4 @@ -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { generateMnemonic } from "@meshsdk/common"; import { deserializeBech32Address } from "@meshsdk/core-cst"; import { EmbeddedWallet } from "@meshsdk/bitcoin"; @@ -47,18 +47,15 @@ export async function clientGenerateWallet( const bitcoinMainnetPubKeyHash = bitcoinMainnetWallet.getPublicKey(); /* cardano */ - const cardanoWallet = new MeshWallet({ + const cardanoWallet = await MeshCardanoHeadlessWallet.fromMnemonic({ + mnemonic: mnemonic.split(" "), networkId: 1, - key: { - type: "mnemonic", - words: mnemonic.split(" "), - }, + walletAddressType: 1, }); - await cardanoWallet.init(); - const cardanoAddresses = await cardanoWallet.getAddresses(); + const cardanoBaseAddress = await cardanoWallet.getChangeAddressBech32(); const cardanoKeyHashes = deserializeBech32Address( - cardanoAddresses.baseAddressBech32!, + cardanoBaseAddress, ); /* spark */ diff --git a/src/functions/client/recovery.test.ts b/src/functions/client/recovery.test.ts index bdbdb8f..230b885 100644 --- a/src/functions/client/recovery.test.ts +++ b/src/functions/client/recovery.test.ts @@ -6,9 +6,9 @@ import { shamirCombine } from "../key-shard"; // Mock external wallet SDKs jest.mock("@meshsdk/wallet", () => ({ - MeshWallet: jest.fn().mockImplementation(() => ({ - init: jest.fn().mockResolvedValue(undefined), - })), + MeshCardanoHeadlessWallet: { + fromMnemonic: jest.fn().mockResolvedValue({}), + }, })); jest.mock("@meshsdk/bitcoin", () => ({ diff --git a/src/functions/key-shard/combine-shards-build-wallet.test.ts b/src/functions/key-shard/combine-shards-build-wallet.test.ts index d417a71..38140e8 100644 --- a/src/functions/key-shard/combine-shards-build-wallet.test.ts +++ b/src/functions/key-shard/combine-shards-build-wallet.test.ts @@ -3,11 +3,14 @@ import { hexToBytes, bytesToString } from "../convertors"; import { shamirCombine } from "./shamir-secret-sharing"; // Mock external wallet SDKs +const mockCardanoWalletInstance = { + getUsedAddressesBech32: jest.fn().mockResolvedValue(["addr_test1..."]), +}; + jest.mock("@meshsdk/wallet", () => ({ - MeshWallet: jest.fn().mockImplementation(() => ({ - init: jest.fn().mockResolvedValue(undefined), - getUsedAddresses: jest.fn().mockResolvedValue(["addr_test1..."]), - })), + MeshCardanoHeadlessWallet: { + fromMnemonic: jest.fn().mockResolvedValue(mockCardanoWalletInstance), + }, })); jest.mock("@meshsdk/bitcoin", () => ({ @@ -28,7 +31,7 @@ jest.mock("@buildonspark/spark-sdk", () => ({ // Import after mocks are set up import { combineShardsBuildWallet } from "./combine-shards-build-wallet"; -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { EmbeddedWallet } from "@meshsdk/bitcoin"; import { SparkWallet } from "@buildonspark/spark-sdk"; @@ -101,38 +104,32 @@ describe("combineShardsBuildWallet", () => { ); }); - it("initializes MeshWallet with correct networkId for testnet", async () => { + it("initializes MeshCardanoHeadlessWallet with correct networkId for testnet", async () => { const mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; const shards = await spiltKeyIntoShards(mnemonic); await combineShardsBuildWallet(0, shards[0]!, shards[1]!); - expect(MeshWallet).toHaveBeenCalledWith( + expect(MeshCardanoHeadlessWallet.fromMnemonic).toHaveBeenCalledWith( expect.objectContaining({ networkId: 0, - key: expect.objectContaining({ - type: "mnemonic", - words: mnemonic.split(" "), - }), + mnemonic: mnemonic.split(" "), }), ); }); - it("initializes MeshWallet with correct networkId for mainnet", async () => { + it("initializes MeshCardanoHeadlessWallet with correct networkId for mainnet", async () => { const mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; const shards = await spiltKeyIntoShards(mnemonic); await combineShardsBuildWallet(1, shards[0]!, shards[1]!); - expect(MeshWallet).toHaveBeenCalledWith( + expect(MeshCardanoHeadlessWallet.fromMnemonic).toHaveBeenCalledWith( expect.objectContaining({ networkId: 1, - key: expect.objectContaining({ - type: "mnemonic", - words: mnemonic.split(" "), - }), + mnemonic: mnemonic.split(" "), }), ); }); @@ -171,16 +168,6 @@ describe("combineShardsBuildWallet", () => { ); }); - it("calls cardanoWallet.init()", async () => { - const mnemonic = - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; - const shards = await spiltKeyIntoShards(mnemonic); - - const result = await combineShardsBuildWallet(0, shards[0]!, shards[1]!); - - expect(result.cardanoWallet.init).toHaveBeenCalled(); - }); - it("passes bitcoinProvider to EmbeddedWallet when provided", async () => { const mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; diff --git a/src/functions/key-shard/combine-shards-build-wallet.ts b/src/functions/key-shard/combine-shards-build-wallet.ts index c5cdb2e..4b83ced 100644 --- a/src/functions/key-shard/combine-shards-build-wallet.ts +++ b/src/functions/key-shard/combine-shards-build-wallet.ts @@ -1,7 +1,8 @@ -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { shamirCombine } from "./shamir-secret-sharing"; import { bytesToString, hexToBytes } from "../convertors"; import { EmbeddedWallet, IBitcoinProvider } from "@meshsdk/bitcoin"; +import { IFetcher } from "@meshsdk/common"; import { SparkWallet } from "@buildonspark/spark-sdk"; export async function combineShardsBuildWallet( @@ -9,6 +10,7 @@ export async function combineShardsBuildWallet( keyShard1: string, keyShard2: string, bitcoinProvider?: IBitcoinProvider, + fetcher?: IFetcher, ) { const _share1 = hexToBytes(keyShard1); const _share2 = hexToBytes(keyShard2); @@ -25,16 +27,13 @@ export async function combineShardsBuildWallet( provider: bitcoinProvider, }); - const cardanoWallet = new MeshWallet({ + const cardanoWallet = await MeshCardanoHeadlessWallet.fromMnemonic({ + mnemonic: mnemonic.split(" "), networkId: networkId, - key: { - type: "mnemonic", - words: mnemonic.split(" "), - }, + walletAddressType: 1, + fetcher, }); - await cardanoWallet.init(); - const { wallet: sparkWallet } = await SparkWallet.initialize({ mnemonicOrSeed: mnemonic, options: { diff --git a/src/sdk/sponsorship/index.ts b/src/sdk/sponsorship/index.ts index 8dd3e63..b03103d 100644 --- a/src/sdk/sponsorship/index.ts +++ b/src/sdk/sponsorship/index.ts @@ -113,8 +113,8 @@ export class Sponsorship { config: SponsorshipConfig; }) { const sponsorWallet = await this.getSponsorWallet(config.projectWalletId); - const sponsorshipWalletUtxos = await sponsorWallet.getUtxos(); - const sponsorshipWalletAddress = await sponsorWallet.getChangeAddress(); + const sponsorshipWalletUtxos = await sponsorWallet.getUtxosMesh(); + const sponsorshipWalletAddress = await sponsorWallet.getChangeAddressBech32(); if (sponsorshipWalletUtxos.length === 0) { throw new Error( "No UTXOs available in the sponsorship wallet. Please fund the wallet.", @@ -328,7 +328,7 @@ export class Sponsorship { throw new Error("Failed to rebuild transaction with selected UTXO."); } - const signedRebuiltTxHex = await sponsorWallet.signTx( + const signedRebuiltTxHex = await sponsorWallet.signTxReturnFullTx( _rebuiltTxHex, true, ); @@ -354,8 +354,8 @@ export class Sponsorship { config: SponsorshipConfig; }) { const wallet = await this.getSponsorWallet(config.projectWalletId); - const utxos = await wallet.getUtxos(); - const changeAddress = await wallet.getChangeAddress(); + const utxos = await wallet.getUtxosMesh(); + const changeAddress = await wallet.getChangeAddressBech32(); // Get any UTXOs that is not the sponsor amount, use these as inputs to create more UTXOs const utxosAsInput = utxos.filter((utxo: any) => { @@ -480,7 +480,7 @@ export class Sponsorship { } const unsignedTx = await txBuilder.complete(); - const signedTx = await wallet.signTx(unsignedTx); + const signedTx = await wallet.signTxReturnFullTx(unsignedTx); const txHash = await this.sdk.providerSubmitter!.submitTx(signedTx); await this.sdk.axiosInstance.post( diff --git a/src/sdk/tokenization/cardano.ts b/src/sdk/tokenization/cardano.ts index b522712..69ff57d 100644 --- a/src/sdk/tokenization/cardano.ts +++ b/src/sdk/tokenization/cardano.ts @@ -1,7 +1,7 @@ import { Web3Sdk } from ".."; import { decryptWithPrivateKey } from "../../functions"; import { MultiChainWalletInfo } from "../../types"; -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { TokenizationTransaction, TokenizationFrozenAddress, @@ -36,14 +36,14 @@ export type { export class TokenizationCardano { private readonly sdk: Web3Sdk; - private wallet: MeshWallet | null = null; + private wallet: MeshCardanoHeadlessWallet | null = null; private walletInfo: MultiChainWalletInfo | null = null; constructor({ sdk }: { sdk: Web3Sdk }) { this.sdk = sdk; } - setWallet(wallet: MeshWallet, walletInfo: MultiChainWalletInfo): void { + setWallet(wallet: MeshCardanoHeadlessWallet, walletInfo: MultiChainWalletInfo): void { this.wallet = wallet; this.walletInfo = walletInfo; } @@ -74,14 +74,10 @@ export class TokenizationCardano { }); const networkId = this.sdk.network === "mainnet" ? 1 : 0; - const wallet = new MeshWallet({ + const wallet = await MeshCardanoHeadlessWallet.fromMnemonic({ + mnemonic: mnemonic.split(" "), networkId, - fetcher: undefined, - submitter: undefined, - key: { - type: "mnemonic", - words: mnemonic.split(" "), - }, + walletAddressType: 1, }); this.wallet = wallet; diff --git a/src/sdk/wallet-developer-controlled/cardano.ts b/src/sdk/wallet-developer-controlled/cardano.ts index 878afb2..8487df3 100644 --- a/src/sdk/wallet-developer-controlled/cardano.ts +++ b/src/sdk/wallet-developer-controlled/cardano.ts @@ -1,5 +1,5 @@ import { Web3Sdk } from ".."; -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { decryptWithPrivateKey } from "../../functions"; import { MultiChainWalletInfo, TokenCreationParams } from "../../types"; @@ -16,9 +16,9 @@ import { MultiChainWalletInfo, TokenCreationParams } from "../../types"; * // Get wallets by tag * const treasuryWallets = await sdk.wallet.cardano.getWalletsByTag("treasury"); * - * // Get a specific wallet with initialized MeshWallet + * // Get a specific wallet with initialized MeshCardanoHeadlessWallet * const { info, wallet } = await sdk.wallet.cardano.getWallet("wallet-id"); - * const addresses = wallet.getAddresses(); + * const address = await wallet.getChangeAddressBech32(); * ``` */ export class CardanoWalletDeveloperControlled { @@ -56,17 +56,17 @@ export class CardanoWalletDeveloperControlled { } /** - * Retrieves a specific Cardano wallet by ID and initializes a MeshWallet instance. + * Retrieves a specific Cardano wallet by ID and initializes a MeshCardanoHeadlessWallet instance. * * @param walletId - The wallet ID to retrieve * @param decryptKey - If true, returns the decrypted mnemonic in wallet info - * @returns Promise resolving to wallet info and initialized MeshWallet + * @returns Promise resolving to wallet info and initialized MeshCardanoHeadlessWallet * * @example * ```typescript * const { info, wallet } = await sdk.wallet.cardano.getWallet("wallet-id"); - * const addresses = wallet.getAddresses(); - * console.log("Base address:", addresses.baseAddressBech32); + * const address = await wallet.getChangeAddressBech32(); + * console.log("Base address:", address); * ``` */ async getWallet( @@ -74,7 +74,7 @@ export class CardanoWalletDeveloperControlled { decryptKey = false, ): Promise<{ info: MultiChainWalletInfo; - wallet: MeshWallet; + wallet: MeshCardanoHeadlessWallet; }> { if (this.sdk.privateKey === undefined) { throw new Error("Private key not found"); @@ -97,16 +97,11 @@ export class CardanoWalletDeveloperControlled { } const networkId = this.sdk.network === "mainnet" ? 1 : 0; - const wallet = new MeshWallet({ + const wallet = await MeshCardanoHeadlessWallet.fromMnemonic({ + mnemonic: mnemonic.split(" "), networkId: networkId, - key: { - type: "mnemonic", - words: mnemonic.split(" "), - }, - fetcher: this.sdk.providerFetcher, - submitter: this.sdk.providerSubmitter, + walletAddressType: 1, }); - await wallet.init(); return { info: web3Wallet, wallet: wallet }; } diff --git a/src/sdk/wallet-developer-controlled/index.test.ts b/src/sdk/wallet-developer-controlled/index.test.ts index 7be78f5..f878f73 100644 --- a/src/sdk/wallet-developer-controlled/index.test.ts +++ b/src/sdk/wallet-developer-controlled/index.test.ts @@ -4,31 +4,21 @@ jest.mock("uuid", () => ({ })); // Mock external wallet SDKs +const mockCardanoWalletInstance = { + getChangeAddressBech32: jest.fn().mockResolvedValue( + "addr_test1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwq2ytjqp", + ), +}; + jest.mock("@meshsdk/wallet", () => ({ - MeshWallet: Object.assign( - jest.fn().mockImplementation(() => ({ - init: jest.fn().mockResolvedValue(undefined), - getAddresses: jest.fn().mockReturnValue({ - baseAddressBech32: - "addr_test1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwq2ytjqp", - }), - })), - { - brew: jest.fn().mockReturnValue([ - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "about", - ]), - }, + MeshCardanoHeadlessWallet: { + fromMnemonic: jest.fn().mockResolvedValue(mockCardanoWalletInstance), + }, +})); + +jest.mock("@meshsdk/common", () => ({ + generateMnemonic: jest.fn().mockResolvedValue( + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", ), })); @@ -67,7 +57,8 @@ jest.mock("../../functions", () => ({ // Import after mocks import { WalletDeveloperControlled } from "./index"; import { Web3Sdk } from "../index"; -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; +import { generateMnemonic } from "@meshsdk/common"; import { IssuerSparkWallet } from "@buildonspark/issuer-sdk"; import { encryptWithPublicKey, decryptWithPrivateKey } from "../../functions"; import { v4 as uuidv4 } from "uuid"; @@ -148,12 +139,12 @@ describe("WalletDeveloperControlled", () => { expect(result).toHaveProperty("cardanoWallet"); }); - it("generates a new mnemonic using MeshWallet.brew", async () => { + it("generates a new mnemonic using generateMnemonic", async () => { const wallet = new WalletDeveloperControlled({ sdk: mockSdk }); await wallet.createWallet(); - expect(MeshWallet.brew).toHaveBeenCalled(); + expect(generateMnemonic).toHaveBeenCalledWith(256); }); it("encrypts mnemonic with project public key", async () => { @@ -172,7 +163,7 @@ describe("WalletDeveloperControlled", () => { await wallet.createWallet(); - expect(MeshWallet).toHaveBeenCalledWith( + expect(MeshCardanoHeadlessWallet.fromMnemonic).toHaveBeenCalledWith( expect.objectContaining({ networkId: 0 }), ); }); @@ -186,7 +177,7 @@ describe("WalletDeveloperControlled", () => { await wallet.createWallet(); - expect(MeshWallet).toHaveBeenCalledWith( + expect(MeshCardanoHeadlessWallet.fromMnemonic).toHaveBeenCalledWith( expect.objectContaining({ networkId: 1 }), ); }); @@ -349,30 +340,27 @@ describe("WalletDeveloperControlled", () => { }); }); - it("creates MeshWallet with decrypted mnemonic", async () => { + it("creates MeshCardanoHeadlessWallet with decrypted mnemonic", async () => { const wallet = new WalletDeveloperControlled({ sdk: mockSdk }); await wallet.initWallet("test-wallet-id"); - expect(MeshWallet).toHaveBeenCalledWith( + expect(MeshCardanoHeadlessWallet.fromMnemonic).toHaveBeenCalledWith( expect.objectContaining({ - key: { - type: "mnemonic", - words: [ - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "abandon", - "about", - ], - }, + mnemonic: [ + "abandon", + "abandon", + "abandon", + "abandon", + "abandon", + "abandon", + "abandon", + "abandon", + "abandon", + "abandon", + "abandon", + "about", + ], }), ); }); diff --git a/src/sdk/wallet-developer-controlled/index.ts b/src/sdk/wallet-developer-controlled/index.ts index ffd5f87..9c3a9db 100644 --- a/src/sdk/wallet-developer-controlled/index.ts +++ b/src/sdk/wallet-developer-controlled/index.ts @@ -6,7 +6,8 @@ import { } from "../../types/core/multi-chain"; import { CardanoWalletDeveloperControlled } from "./cardano"; import { SparkIssuerWalletDeveloperControlled } from "./spark-issuer"; -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; +import { generateMnemonic } from "@meshsdk/common"; import { IssuerSparkWallet } from "@buildonspark/issuer-sdk"; import { deserializeBech32Address } from "@meshsdk/core-cst"; import { encryptWithPublicKey, decryptWithPrivateKey } from "../../functions"; @@ -75,7 +76,7 @@ export class WalletDeveloperControlled { ): Promise<{ info: MultiChainWalletInfo; sparkIssuerWallet: IssuerSparkWallet; - cardanoWallet: MeshWallet; + cardanoWallet: MeshCardanoHeadlessWallet; }> { const project = await this.sdk.getProject(); if (!project.publicKey) { @@ -84,19 +85,17 @@ export class WalletDeveloperControlled { const networkId = this.sdk.network === "mainnet" ? 1 : 0; const walletId = uuidv4(); - const mnemonic = MeshWallet.brew() as string[]; + const mnemonic = (await generateMnemonic(256)).split(" "); const encryptedKey = await encryptWithPublicKey({ publicKey: project.publicKey, data: mnemonic.join(" "), }); - const cardanoWallet = new MeshWallet({ + const cardanoWallet = await MeshCardanoHeadlessWallet.fromMnemonic({ + mnemonic: mnemonic, networkId: networkId, - key: { type: "mnemonic", words: mnemonic }, - fetcher: this.sdk.providerFetcher, - submitter: this.sdk.providerSubmitter, + walletAddressType: 1, }); - await cardanoWallet.init(); const [{ wallet: sparkMainnetWallet }, { wallet: sparkRegtestWallet }] = await Promise.all([ @@ -110,9 +109,9 @@ export class WalletDeveloperControlled { }), ]); - const addresses = cardanoWallet.getAddresses(); + const baseAddress = await cardanoWallet.getChangeAddressBech32(); const { pubKeyHash, stakeCredentialHash } = deserializeBech32Address( - addresses.baseAddressBech32!, + baseAddress, ); const [mainnetPublicKey, regtestPublicKey] = await Promise.all([ sparkMainnetWallet.getIdentityPublicKey(), @@ -162,14 +161,14 @@ export class WalletDeveloperControlled { * // Get Spark wallet address * const sparkAddress = await sparkWallet.getSparkAddress(); * - * // Get Cardano wallet addresses - * const addresses = cardanoWallet.getAddresses(); + * // Get Cardano wallet address + * const address = await cardanoWallet.getChangeAddressBech32(); * ``` */ async initWallet(walletId: string): Promise<{ info: MultiChainWalletInfo; sparkWallet: IssuerSparkWallet; - cardanoWallet: MeshWallet; + cardanoWallet: MeshCardanoHeadlessWallet; }> { if (!this.sdk.privateKey) { throw new Error( @@ -184,13 +183,11 @@ export class WalletDeveloperControlled { encryptedDataJSON: walletInfo.key, }); - const cardanoWallet = new MeshWallet({ + const cardanoWallet = await MeshCardanoHeadlessWallet.fromMnemonic({ + mnemonic: sharedMnemonic.split(" "), networkId: effectiveNetworkId, - key: { type: "mnemonic", words: sharedMnemonic.split(" ") }, - fetcher: this.sdk.providerFetcher, - submitter: this.sdk.providerSubmitter, + walletAddressType: 1, }); - await cardanoWallet.init(); const sparkNetwork = effectiveNetworkId === 1 ? "MAINNET" : "REGTEST"; const { wallet: sparkWallet } = await IssuerSparkWallet.initialize({ @@ -246,13 +243,11 @@ export class WalletDeveloperControlled { walletInfo.chains.cardano && mnemonic ) { - const cardanoWallet = new MeshWallet({ + const cardanoWallet = await MeshCardanoHeadlessWallet.fromMnemonic({ + mnemonic: mnemonic.split(" "), networkId: networkId, - key: { type: "mnemonic", words: mnemonic.split(" ") }, - fetcher: this.sdk.providerFetcher, - submitter: this.sdk.providerSubmitter, + walletAddressType: 1, }); - await cardanoWallet.init(); instance.cardanoWallet = cardanoWallet; } diff --git a/src/types/core/multi-chain.ts b/src/types/core/multi-chain.ts index 19a1cc1..c05a438 100644 --- a/src/types/core/multi-chain.ts +++ b/src/types/core/multi-chain.ts @@ -1,4 +1,4 @@ -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { IssuerSparkWallet } from "@buildonspark/issuer-sdk"; import { MultiChainWalletInfo as ContractWalletInfo, @@ -33,7 +33,7 @@ export { validateMultiChainWalletInfo, isValidMultiChainWalletInfo }; */ export interface MultiChainWalletInstance { info: MultiChainWalletInfo; - cardanoWallet?: MeshWallet; + cardanoWallet?: MeshCardanoHeadlessWallet; sparkIssuerWallet?: IssuerSparkWallet; } diff --git a/src/wallet-user-controlled/web3-wallet.ts b/src/wallet-user-controlled/web3-wallet.ts index 93b72d3..750f7fe 100644 --- a/src/wallet-user-controlled/web3-wallet.ts +++ b/src/wallet-user-controlled/web3-wallet.ts @@ -1,4 +1,4 @@ -import { MeshWallet } from "@meshsdk/wallet"; +import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { IFetcher, ISubmitter } from "@meshsdk/common"; import { EmbeddedWallet, @@ -42,7 +42,7 @@ type Web3WalletContructorOptions = { projectId?: string; appUrl?: string; user?: UserSocialData; - cardano: MeshWallet; + cardano: MeshCardanoHeadlessWallet; bitcoin: EmbeddedWallet; spark: Web3SparkWallet; }; @@ -60,7 +60,7 @@ export class Web3Wallet { projectId?: string; appUrl: string = "https://utxos.dev/"; user?: UserSocialData; - cardano: MeshWallet; + cardano: MeshCardanoHeadlessWallet; bitcoin: EmbeddedWallet; spark: Web3SparkWallet; networkId: 0 | 1; @@ -355,23 +355,37 @@ export class Web3Wallet { fetcher: IFetcher | undefined; submitter: ISubmitter | undefined; keyHashes: Web3WalletKeyHashes; - }): Promise { - const cardanoWallet = new MeshWallet({ - networkId: options.networkId, - key: { - type: "address", - address: getCardanoAddressFromPubkey( - options.keyHashes.cardanoPubKeyHash, - options.keyHashes.cardanoStakeCredentialHash, - options.networkId, - ), + }): Promise { + const address = getCardanoAddressFromPubkey( + options.keyHashes.cardanoPubKeyHash, + options.keyHashes.cardanoStakeCredentialHash, + options.networkId, + ); + + const cardanoWallet = await MeshCardanoHeadlessWallet.fromCredentialSources({ + paymentCredentialSource: { + type: "signer", + signer: { + getPublicKey: async () => options.keyHashes.cardanoPubKeyHash, + getPublicKeyHash: async () => options.keyHashes.cardanoPubKeyHash, + sign: async () => "", + verify: async () => false, + }, }, - fetcher: options.fetcher, - submitter: options.submitter, + stakeCredentialSource: options.keyHashes.cardanoStakeCredentialHash ? { + type: "signer", + signer: { + getPublicKey: async () => options.keyHashes.cardanoStakeCredentialHash, + getPublicKeyHash: async () => options.keyHashes.cardanoStakeCredentialHash, + sign: async () => "", + verify: async () => false, + }, + } : undefined, + networkId: options.networkId, + walletAddressType: 1, }); - await cardanoWallet.init(); - cardanoWallet.signTx = async ( + (cardanoWallet as any).signTx = async ( unsignedTx: string, partialSign = false, returnFullTx = true, @@ -404,7 +418,39 @@ export class Web3Wallet { return res.data.tx; }; - cardanoWallet.signData = async (payload: string, address?: string) => { + (cardanoWallet as any).signTxReturnFullTx = async ( + unsignedTx: string, + partialSign = false, + ) => { + const res: OpenWindowResult = await openWindow( + { + method: "cardano-sign-tx", + projectId: options.projectId, + unsignedTx, + partialSign: partialSign === true ? "true" : "false", + returnFullTx: "true", + networkId: String(options.networkId), + }, + options.appUrl, + ); + + if (res.success === false) + throw new ApiError({ + code: 2, + info: "UserDeclined - User declined to sign the message.", + }); + + if (res.data.method !== "cardano-sign-tx") { + throw new ApiError({ + code: 2, + info: "Received the wrong response from the iframe.", + }); + } + + return res.data.tx; + }; + + (cardanoWallet as any).signData = async (address: string, payload: string) => { const res: OpenWindowResult = await openWindow( { method: "cardano-sign-data",