Gathering detailed insights and metrics for @turnkey/wallet-stamper
Gathering detailed insights and metrics for @turnkey/wallet-stamper
Gathering detailed insights and metrics for @turnkey/wallet-stamper
Gathering detailed insights and metrics for @turnkey/wallet-stamper
npm install @turnkey/wallet-stamper
Typescript
Module System
Node Version
NPM Version
80.6
Supply Chain
98.6
Quality
90.7
Maintenance
100
Vulnerability
100
License
TypeScript (94.14%)
JavaScript (4.45%)
CSS (1.29%)
Solidity (0.11%)
Verify real, reachable, and deliverable emails with instant MX records, SMTP checks, and disposable email detection.
Total Downloads
43,246
Last Day
859
Last Week
5,177
Last Month
18,964
Last Year
43,246
Apache-2.0 License
63 Stars
1,982 Commits
18 Forks
5 Watchers
91 Branches
25 Contributors
Updated on Feb 28, 2025
Minified
Minified + Gzipped
Latest Version
1.0.3
Package Id
@turnkey/wallet-stamper@1.0.3
Unpacked Size
56.87 kB
Size
15.72 kB
File Count
41
NPM Version
9.8.1
Node Version
18.18.2
Published on
Feb 12, 2025
Cumulative downloads
Total Downloads
Last Day
-8.9%
859
Compared to previous day
Last Week
-2.7%
5,177
Compared to previous week
Last Month
60%
18,964
Compared to previous month
Last Year
0%
43,246
Compared to previous year
3
7
1
The @turnkey/wallet-stamper
package provides a mechanism to stamp requests using a wallet public key and signature. This package supports both Solana and Ethereum wallets, allowing for seamless integration with various blockchain applications.
Before you start using the Turnkey Wallet Stamper, make sure to install the necessary packages in your project. This guide assumes you have a Node.js environment ready for development.
Install the required packages using NPM, Yarn, or PNPM:
1npm install @turnkey/wallet-stamper @turnkey/http
To use the wallet stamper, you must add the user's wallet public key as an API key authenticator. This can be achieved either by creating a sub-organization activity or by generating a new API key and passing in the wallet's public key.
The API key stamper is necessary because we need to use the parent organization's API key to add the authenticator initially. Once this is done, the wallet can stamp activity requests independently without needing the parent organization's API private and public keys.
Below are the steps to add a Solana public key as a wallet authenticator:
1const apiKeyStamper = new ApiKeyStamper({ 2 apiPublicKey: process.env.API_PUBLIC_KEY ?? "", 3 apiPrivateKey: process.env.API_PRIVATE_KEY ?? "", 4}); 5 6const client = new TurnkeyClient({ baseUrl: BASE_URL }, apiKeyStamper); 7 8const activityPoller = createActivityPoller({ 9 client, 10 requestFn: client.createApiKeys, 11}); 12 13// See "Example: Signing with a Solana Wallet" below for how to implement the SolanaWallet interface 14const mockWallet = new MockSolanaWallet(); 15 16// This is the public key of the wallet that will be added as an API key and used to stamp future requests 17const publicKey = mockWallet.recoverPublicKey(); 18 19// The userId of the user that we will add the wallet public key as an authenticator 20const userId = "f4a5e6b4-3b9c-4f69-b7f6-9c2f456a4d23"; 21 22// We set the curve type to 'API_KEY_CURVE_ED25519' for solana wallets 23// If using an Ethereum wallet, set the curve type to 'API_KEY_CURVE_SECP256K1' 24const curveType = "API_KEY_CURVE_ED25519"; 25 26const result = activityPoller({ 27 type: "ACTIVITY_TYPE_CREATE_API_KEYS_V2", 28 timestampMs: new Date().getTime().toString(), 29 organizationId: "acd0bc97-2af5-475b-bc34-0fa7ca3bdc75", 30 parameters: { 31 apiKeys: [ 32 { 33 apiKeyName: "solana-wallet", 34 publicKey, 35 curveType, 36 }, 37 ], 38 userId, 39 }, 40});
To use the @turnkey/wallet-stamper
package, follow these steps:
Choose Your Wallet Type: Decide whether you will use an EVM-based wallet (e.g., Ethereum) or a Solana-based wallet.
Implement the Wallet Interface: Depending on your chosen blockchain, implement the wallet interface. This involves creating methods to sign messages and recover public keys.
Note: We've provided a default implementation for Ethereum wallets via the
EthereumWallet
class. For custom implementations, you may implement theWalletInterface
yourself.
Instantiate the WalletStamper: Create an instance of the WalletStamper
using the wallet interface.
Instantiate the TurnkeyClient: Create an instance of the TurnkeyClient
with the WalletStamper
instance.
Stamp Requests: Now when making request using the TurnkeyClient
, the wallet stamper will automatically stamp the request with the user's wallet public key and signature.
In this example, we are using a local Solana wallet.
For information on using an injected Solana wallet such as Solflare, please refer to the with-wallet-stamper
example.
1import { Keypair } from "@solana/web3.js"; 2import { decodeUTF8 } from "tweetnacl-util"; 3import nacl from "tweetnacl"; 4import { TurnkeyClient } from "@turnkey/http"; 5import { WalletStamper, SolanaWalletInterface } from "@turnkey/wallet-stamper"; 6 7class SolanaWallet implements SolanaWalletInterface { 8 keypair = Keypair.fromSecretKey(SOLANA_PRIVATE_KEY); 9 type = "solana" as const; 10 11 async signMessage(message: string): Promise<string> { 12 const messageBytes = decodeUTF8(message); 13 const signature = nacl.sign.detached(messageBytes, this.keypair.secretKey); 14 return Buffer.from(signature).toString("hex"); 15 } 16 17 async getPublicKey(): Promise<string> { 18 // Convert the base24 encoded Solana wallet public key (the one displayed in the wallet) 19 // into the ed25519 decoded public key 20 const ed25519PublicKey = Buffer.from( 21 this.keypair.publicKey.toBuffer(), 22 ).toString("hex"); 23 return ed25519PublicKey; 24 } 25} 26 27// Instantiate the WalletStamper with the SolanaWallet 28const walletStamper = new WalletStamper(new SolanaWallet()); 29 30// Instantiate the TurnkeyClient with the WalletStamper 31const client = new TurnkeyClient({ baseUrl: BASE_URL }, walletStamper); 32 33// Call getWhoami to get the sub org's organizationId and userId passing in the parent org id 34// whoami { organizationId: string; organizationName: string; userId: string; username: string; } 35const whoami = await client.getWhoami({ 36 organizationId: process.env.NEXT_PUBLIC_ORGANIZATION_ID, 37}); 38 39// Now that we have the sub organization id, we can make requests using that sub org id 40 41// Get the wallets for this sub organization 42const wallets = await client.getWallets({ 43 organizationId: whoami.organizationId, 44});
The main distinction between signing with an Ethereum Wallet and a Solana Wallet lies in how the public key is obtained. For Solana, the public key can be directly derived from the wallet. In contrast, with Ethereum, the secp256k1 public key isn't directly accessible. Instead, you need to first obtain a signature from the user and then recover the public key from that signature.
1import { 2 createWalletClient, 3 custom, 4 recoverPublicKey, 5 hashMessage, 6} from "viem"; 7import { privateKeyToAccount } from "viem/accounts"; 8import { mainnet } from "viem/chains"; 9 10import { WalletStamper, EthereumWallet } from "@turnkey/wallet-stamper"; 11 12// Instantiate the WalletStamper with the EthereumWallet 13const walletStamper = new WalletStamper(new EthereumWallet()); 14 15// Instantiate the TurnkeyClient with the WalletStamper 16const client = new TurnkeyClient({ baseUrl: BASE_URL }, walletStamper); 17 18// Call getWhoami to get the sub-org's organizationId and userId passing in the parent org id 19// whoami { organizationId: string; organizationName: string; userId: string; username: string; } 20const whoami = await client.getWhoami({ 21 organizationId: process.env.ORGANIZATION_ID, 22}); 23 24let subOrganizationId = whoami?.organizationId; 25 26// User does not yet have a sub-organization, so we need to create one 27if (!subOrganizationId) { 28 // We'll need to use the parent org's API keys to create the sub-org on behalf of the user 29 const { ApiKeyStamper } = await import("@turnkey/api-key-stamper"); 30 31 // Instantiate the TurnkeyClient with the ApiKeyStamper 32 const parentOrgClient = new TurnkeyClient( 33 { baseUrl: BASE_URL }, 34 new ApiKeyStamper({ 35 // In practice we'll want to ensure these keys do not get exposed to the client 36 apiPublicKey: process.env.API_PUBLIC_KEY ?? "", 37 apiPrivateKey: process.env.API_PRIVATE_KEY ?? "", 38 }), 39 ); 40 41 const apiKeys = [ 42 { 43 apiKeyName: "Wallet Auth - Embedded Wallet", 44 // The public key of the wallet that will be added as an API key and used to stamp future requests 45 publicKey, 46 // We set the curve type to 'API_KEY_CURVE_ED25519' for solana wallets 47 // If using an Ethereum wallet, set the curve type to 'API_KEY_CURVE_SECP256K1' 48 curveType, 49 }, 50 ]; 51 52 const subOrg = await parentOrgClient.createSubOrganization({ 53 organizationId: process.env.ORGANIZATION_ID, 54 subOrganizationName: `Sub Org - ${publicKey}`, 55 rootUsers: [ 56 { 57 // Replace with user provided values 58 userName: "New User", 59 userEmail: "wallet@domain.com", 60 apiKeys, 61 }, 62 ], 63 rootQuorumThreshold: 1, 64 wallet: { 65 walletName: "Default Wallet", 66 accounts: DEFAULT_ETHEREUM_ACCOUNTS, 67 }, 68 }); 69 70 subOrganizationId = subOrg.subOrganizationId; 71} 72 73// Get the wallets for this sub-organization 74const wallets = await client.getWallets({ 75 organizationId: subOrganizationId, 76});
Contributions are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request.
The @turnkey/wallet-stamper
package is licensed under the MIT License.
No vulnerabilities found.
No security vulnerabilities found.