Integrate with Turnkey
The steps given below contain instructions on how to integrate Enclave's SDK with an application that uses Turnkey's React SDK
Last updated
npm install enclavemoneyimport { Enclave, SignMode } from 'enclavemoney';
const API_KEY = 'your-api-key-here';
const enclave = new Enclave(API_KEY);import { useState, useEffect } from "react";
import { useTurnkey } from "@turnkey/sdk-react";
import { formatUnits, parseUnits, isAddress, ethers, getBytes } from 'ethers';
....
const { turnkey, getActiveClient } = useTurnkey();
const client = await getActiveClient();
// The user's sub-organization id
const organizationId = user?.organization.organizationId;
// Get the user's wallets
const wallets = await client?.getWallets({
organizationId,
});
// Get the first wallet of the user
const walletId = wallets?.wallets[0].walletId ?? "";
// Use the `walletId` to get the accounts associated with the wallet
const accounts = await client?.getWalletAccounts({
organizationId,
walletId,
});
const signingKey = accounts?.accounts[0].address;
const account = await enclave.createSmartAccount(signingKey);
console.log('Smart Account created:', account.wallet.scw_address);
// Define the transaction details
// Define the USDC contract address on Optimism
const usdcContractAddress = '<Insert USDC Contract Address for Chain ID>';
// Define the recipient address and amount to transfer
const recipientAddress = '0x...'; // Replace with the recipient's address
const amount = ethers.parseUnits('1', 6); // Amount of USDC to transfer (1 USDC)
// Create the call data for the ERC20 transfer
const erc20Interface = new ethers.Interface([
'function transfer(address to, uint256 amount)'
]);
const encodedData = erc20Interface.encodeFunctionData('transfer', [recipientAddress, amount]);
const transactionDetails = [{
encodedData,
targetContractAddress: usdcContractAddress,
value: 0 // Assuming no ETH is being transferred, only USDC
}];
// Define the order data - Describes how much the user wants to spend from their chain-abstracted balances
// Understanding order type
// AMOUNT_OUT: User needs 100 USDC on the target network. The user will be charged 100 + fees.
// AMOUNT_IN : User is charged 100 USDC and receives (100 - fees) on target network
const orderData = {
amount: amount.toString(), // Amount of USDC required for the transfer
type: 'AMOUNT_OUT'
};
// Build the transaction
const builtTxn = await enclave.buildTransaction(
transactionDetails,
chainId, // chainId of the network you want to execute the transaction on
account.wallet.scw_address, // User's smart account address
orderData,
undefined, // Pass custom ERC4337 paymaster signature if required
SignMode.ECDSA // ECDSA Signature Mode (for secp256k1)
);const turnkeySigner = new TurnkeySigner({
client: client,
organizationId: user.organization.organizationId,
signWith: accounts.accounts[0].address,
})
console.log("UserOpHash To Sign: ", builtTxn.messageToSign);
const msgBytes = getBytes(builtTxn.messageToSign);
const signature = await turnkeySigner.signMessage(msgBytes);const txnResult = await enclave.submitTransaction(
signature,
builtTxn.userOp,
chainId, // chainId of the network you want to execute the transaction on
enclaveAddress,
SignMode.ECDSA
);