diff --git a/package-lock.json b/package-lock.json index 61eca4a..334f799 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "near-fastauth-wallet", - "version": "2.0.1", + "version": "2.0.2-beta.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "near-fastauth-wallet", - "version": "2.0.1", + "version": "2.0.2-beta.10", "license": "MIT", "dependencies": { "@ant-design/icons": "^5.3.6", @@ -17,7 +17,7 @@ "antd": "^5.12.8", "class-variance-authority": "^0.7.0", "js-sha256": "^0.11.0", - "multichain-tools": "^1.0.8", + "multichain-tools": "2.0.14-beta.10", "near-api-js": "^2.1.4", "tslib": "^2.3.0", "usehooks-ts": "^2.9.2" @@ -5956,6 +5956,12 @@ } ] }, + "node_modules/canonicalize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.0.0.tgz", + "integrity": "sha512-ulDEYPv7asdKvqahuAY35c1selLdzDwHqugK92hfkzvlDCwXRRelDkR+Er33md/PtnpqHemgkuDPanZ4fiYZ8w==", + "license": "Apache-2.0" + }, "node_modules/capability": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/capability/-/capability-0.2.5.tgz", @@ -8343,6 +8349,12 @@ "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.11.0.tgz", "integrity": "sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q==" }, + "node_modules/js-sha3": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz", + "integrity": "sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -8713,6 +8725,12 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "dev": true }, + "node_modules/lodash.pickby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", + "integrity": "sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q==", + "license": "MIT" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -8966,16 +8984,20 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multichain-tools": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/multichain-tools/-/multichain-tools-1.0.12.tgz", - "integrity": "sha512-O5o9bkjAbzqqTr5oWJ5lUhWlcA3ByIzPydNtYkVNPGt5njnJ/l3fwF/EVwFsji/sNguCn7Mpi/l4TFrS2wMQQA==", + "version": "2.0.14-beta.10", + "resolved": "https://registry.npmjs.org/multichain-tools/-/multichain-tools-2.0.14-beta.10.tgz", + "integrity": "sha512-qdqVAs9OZ5sm1nfZLBEqJHU9KSwl04NYmApYQcQRMfs9/9xVKy4VnQFoR58VNClMiUH2qGUXUCisdWC3YvPL/w==", + "license": "ISC", "dependencies": { "axios": "^1.6.8", "bitcoinjs-lib": "^6.1.5", "bn.js": "^5.2.1", + "canonicalize": "^2.0.0", "coinselect": "^3.1.13", "elliptic": "^6.5.5", "ethers": "^6.11.1", + "js-sha3": "^0.9.3", + "lodash.pickby": "^4.6.0", "near-api-js": "^3.0.4" } }, diff --git a/package.json b/package.json index a9b1b6e..76fd546 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { "name": "near-fastauth-wallet", - "version": "2.0.1", + "version": "2.0.2-beta.10", "license": "MIT", "scripts": { "build": "nx build --buildLibsFromSource --skip-nx-cache", - "deploy": "cd dist/near-fastauth-wallet && npm publish", + "deploy": "npm run build && cd dist/near-fastauth-wallet && npm publish", + "deploy:beta": "npm run build && cd dist/near-fastauth-wallet && npm publish --tag beta", "test": "nx test", "watch": "nodemon" }, @@ -17,7 +18,7 @@ "antd": "^5.12.8", "class-variance-authority": "^0.7.0", "js-sha256": "^0.11.0", - "multichain-tools": "^1.0.8", + "multichain-tools": "2.0.14-beta.10", "near-api-js": "^2.1.4", "tslib": "^2.3.0", "usehooks-ts": "^2.9.2" @@ -55,4 +56,4 @@ "type": "commonjs", "main": "./src/index.js", "typings": "./src/index.d.ts" -} +} \ No newline at end of file diff --git a/src/lib/fastAuthWalletConnection.ts b/src/lib/fastAuthWalletConnection.ts index 53e911b..807a28b 100644 --- a/src/lib/fastAuthWalletConnection.ts +++ b/src/lib/fastAuthWalletConnection.ts @@ -4,7 +4,6 @@ import type { Near, WalletConnection, } from 'near-api-js'; -import * as nearAPI from 'near-api-js'; import { KeyPair, utils } from 'near-api-js'; import { ConnectedWalletAccount } from 'near-api-js'; import { deserialize, serialize } from 'near-api-js/lib/utils/serialize'; @@ -18,6 +17,12 @@ import { loadIframeDialog } from '../ui/reactApp'; import { SignedMessage, SignMessageParams } from '@near-wallet-selector/core'; import { PublicKey } from 'near-api-js/lib/utils'; import { sha256 } from 'js-sha256'; +import { + BitcoinRequest, + BTCNetworkIds, + EVMRequest, + KeyDerivationPath, +} from 'multichain-tools'; const LOGIN_PATH = '/login/'; const CREATE_ACCOUNT_PATH = '/create-account/'; @@ -58,29 +63,24 @@ interface RequestSignTransactionsOptions { meta?: string; } -interface BaseSendMultichainMessage { - chain: number; - domain?: string; - to: string; - value: bigint; - meta?: { [k: string]: any }; - from: string; -} - -type EvmSendMultichainMessage = BaseSendMultichainMessage & { - chainId: bigint; - maxFeePerGas?: bigint; - maxPriorityFeePerGas?: bigint; - gasLimit?: number; -}; - -type BTCSendMultichainMessage = BaseSendMultichainMessage & { - network: 'mainnet' | 'testnet'; -}; - -type SendMultichainMessage = - | BTCSendMultichainMessage - | EvmSendMultichainMessage; +// This type should be kept in sync with fast-auth-signer receiving message: https://github.com/near/fast-auth-signer/blob/8d2726f5fe007d7ae011dec245692ac7499aff0c/packages/near-fast-auth-signer/src/components/SignMultichain/types.ts#L1 +export type SendMultichainMessage = + | (Omit< + EVMRequest, + 'nearAuthentication' | 'chainConfig' | 'derivationPath' + > & { + chainConfig?: Partial; + derivationPath: Omit & { chain: 60 }; + }) + | (Omit< + BitcoinRequest, + 'nearAuthentication' | 'chainConfig' | 'derivationPath' + > & { + chainConfig: { + network: BTCNetworkIds; + } & Partial>; + derivationPath: Omit & { chain: 0 }; + }); export class FastAuthWalletConnection { /** @hidden */ diff --git a/src/lib/near-fastauth-wallet.ts b/src/lib/near-fastauth-wallet.ts index 89635c4..dbe017f 100644 --- a/src/lib/near-fastauth-wallet.ts +++ b/src/lib/near-fastauth-wallet.ts @@ -16,15 +16,17 @@ import * as nearAPI from 'near-api-js'; import BN from 'bn.js'; import { - NearNetworkIds, - ChainSignatureContracts, - BTCNetworkIds, - fetchDerivedBTCAddress, + type FetchEVMAddressRequest, + type BitcoinPublicKeyAndAddressRequest, fetchDerivedEVMAddress, + fetchDerivedBTCAddressAndPublicKey, } from 'multichain-tools'; import icon from './fast-auth-icon'; -import { FastAuthWalletConnection } from './fastAuthWalletConnection'; +import { + FastAuthWalletConnection, + type SendMultichainMessage, +} from './fastAuthWalletConnection'; export interface FastAuthWalletParams { walletUrl?: string; @@ -46,21 +48,53 @@ interface FastAuthWalletState { near: any; } -interface DerivedAddressParamEVM { - type: 'EVM'; - signerId: string; - path: string; - networkId: NearNetworkIds; - contract: ChainSignatureContracts; +// Should be maintained until these methods are added through NEP to the wallet interface +interface FastAuthSignInParams { + email?: string; + accountId?: string; + isRecovery?: boolean; } -interface DerivedAddressParamBTC { - type: 'BTC'; - signerId: string; - path: string; - networkId: NearNetworkIds; - btcNetworkId: BTCNetworkIds; - contract: ChainSignatureContracts; +type ExtendedSignIn = ( + params: Parameters[0] & FastAuthSignInParams +) => ReturnType; +interface FastAuthBrowserWallet extends BrowserWallet { + signIn: ExtendedSignIn; + + signAndSendDelegateAction(params: { + receiverId: string; + actions: Action[]; + }): Promise; + + signAndSendDelegateActions(params: { + transactions: Optional[]; + callbackUrl?: string; + }): Promise; + + setRelayerUrl(params: { relayerUrl: string }): void; + + resetRelayerUrl(): void; + + verifySignMessage( + message: SignMessageParams, + signedMessage: SignedMessage + ): Promise; + + getDerivedAddress( + args: + | (Omit & { + path: Omit & { + chain: 60; + }; + }) + | (Omit & { + path: Omit & { + chain: 0; + }; + }) + ): Promise; + + signMultiChainTransaction(data: SendMultichainMessage): Promise; } const resolveWalletUrl = (network: Network, walletUrl?: string) => { @@ -100,8 +134,8 @@ const setupWalletState = async ( }; }; -const FastAuthWallet: WalletBehaviourFactory< - BrowserWallet, +export const FastAuthWallet: WalletBehaviourFactory< + FastAuthBrowserWallet, { params: FastAuthWalletExtraOptions } > = async ({ metadata, options, store, params, logger }) => { const _state = await setupWalletState(params, options.network); @@ -297,7 +331,7 @@ const FastAuthWallet: WalletBehaviourFactory< email, accountId, isRecovery, - }: any) { + }) { const existingAccounts = await getAccounts(); if (existingAccounts.length) { @@ -345,70 +379,32 @@ const FastAuthWallet: WalletBehaviourFactory< }); }, - async signAndSendDelegateAction({ - receiverId, - actions, - }: { - receiverId: string; - actions: Action[]; - }): Promise { + async signAndSendDelegateAction({ receiverId, actions }) { await _signAndSendWithRelayer({ transactions: [{ receiverId, actions }], }); }, - async signAndSendDelegateActions({ - transactions, - callbackUrl, - }: { - transactions: Optional[]; - callbackUrl?: string; - }): Promise { + async signAndSendDelegateActions({ transactions, callbackUrl }) { await _signAndSendWithRelayer({ transactions, callbackUrl, }); }, - async getDerivedAddress( - args: DerivedAddressParamEVM | DerivedAddressParamBTC - ) { - if (args.type === 'EVM') { - return await fetchDerivedEVMAddress( - args.signerId, - args.path, - args.networkId, - args.contract - ); - } else if (args.type === 'BTC') { - const address = await fetchDerivedBTCAddress( - args.signerId, - args.path, - args.networkId, - args.btcNetworkId, - args.contract - ); - return address; - } else { - throw new Error('Unsupported chain type'); - } - }, - async signMultiChainTransaction(data) { - await _state.wallet.requestSignMultiChain(data); - }, setRelayerUrl({ relayerUrl: relayerUrlArg }) { relayerUrl = relayerUrlArg; }, + resetRelayerUrl() { relayerUrl = params.relayerUrl; }, + async signMessage(data) { return _state.wallet.requestSignMessage(data); }, - async verifySignMessage( - message: SignMessageParams, - signedMessage: SignedMessage - ): Promise { + + async verifySignMessage(message, signedMessage) { const accessKeys = await _state.wallet.account().getAccessKeys(); const isFullAccessKey = accessKeys.some( (key) => @@ -422,6 +418,25 @@ const FastAuthWallet: WalletBehaviourFactory< return _state.wallet.verifySignMessage(message, signedMessage); }, + + async getDerivedAddress(args) { + if (args.path.chain === 60) { + return await fetchDerivedEVMAddress(args); + } else if (args.path.chain === 0) { + return ( + await fetchDerivedBTCAddressAndPublicKey( + // TypeScript can't infer this from the if clause above, so we need to provide a type assertion + args as BitcoinPublicKeyAndAddressRequest + ) + ).address; + } else { + throw new Error('Unsupported chain type'); + } + }, + + async signMultiChainTransaction(data) { + await _state.wallet.requestSignMultiChain(data); + }, }; };