Enhance Privy integration by adding getWalletIdFromAddress function to retrieve wallet IDs directly from addresses. Update callContract and related methods to utilize the new function for improved transaction handling. Modify tests to reflect changes in wallet address handling and ensure accurate position management.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import {Abi, Address, encodeFunctionData, PublicClient, withRetry} from "viem";
|
import {Abi, Address, encodeFunctionData, PublicClient, withRetry} from "viem";
|
||||||
import {getChainName, getPrivyClient, getAuthorizationContext} from '../../../plugins/custom/privy.js';
|
import {getChainName, getPrivyClient, getAuthorizationContext, getWalletIdFromAddress} from '../../../plugins/custom/privy.js';
|
||||||
|
|
||||||
import type {GmxSdk} from "../index.js";
|
import type {GmxSdk} from "../index.js";
|
||||||
import {bigMath} from "./bigmath.js";
|
import {bigMath} from "./bigmath.js";
|
||||||
@@ -125,6 +125,7 @@ export async function getGasLimit(
|
|||||||
export interface CallContractOpts {
|
export interface CallContractOpts {
|
||||||
value?: bigint | number;
|
value?: bigint | number;
|
||||||
gasLimit?: bigint | number;
|
gasLimit?: bigint | number;
|
||||||
|
did?: string; // Privy DID (user_id) to filter wallets
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function callContract(
|
export async function callContract(
|
||||||
@@ -236,13 +237,10 @@ export async function callContract(
|
|||||||
console.log('Method', method)
|
console.log('Method', method)
|
||||||
console.log('Params', params)
|
console.log('Params', params)
|
||||||
|
|
||||||
const wallets = await privy.wallets().list();
|
const walletId = await getWalletIdFromAddress(sdk.config.account);
|
||||||
console.log('Wallets', wallets)
|
|
||||||
const currentWallet = wallets.data.find((wallet: any) => wallet.address === sdk.config.account);
|
|
||||||
console.log('walletId', currentWallet)
|
|
||||||
|
|
||||||
const response = await privy.wallets().ethereum().sendTransaction(
|
const response = await privy.wallets().ethereum().sendTransaction(
|
||||||
currentWallet.id,
|
walletId,
|
||||||
{
|
{
|
||||||
caip2: networkName,
|
caip2: networkName,
|
||||||
params: {
|
params: {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {getClientForAddress, getTokenDataFromTicker} from './gmx.js'
|
|||||||
import {Address, erc20Abi} from 'viem'
|
import {Address, erc20Abi} from 'viem'
|
||||||
import {Balance, Chain, Ticker} from '../../generated/ManagingApiTypes.js'
|
import {Balance, Chain, Ticker} from '../../generated/ManagingApiTypes.js'
|
||||||
import {getCachedPrivySecrets} from './privy-secrets.js'
|
import {getCachedPrivySecrets} from './privy-secrets.js'
|
||||||
import Token from '../../generated/gmxsdk/abis/Token.js'
|
|
||||||
|
|
||||||
// Load environment variables in non-production only
|
// Load environment variables in non-production only
|
||||||
if (process.env.NODE_ENV !== 'production') dotenv.config()
|
if (process.env.NODE_ENV !== 'production') dotenv.config()
|
||||||
@@ -281,6 +280,44 @@ export const getAuthorizationContext = (fastify?: FastifyInstance): Authorizatio
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Privy wallet ID from a wallet address
|
||||||
|
* Fetches the user by wallet address and extracts the wallet ID directly from linked_accounts
|
||||||
|
* @param address The wallet address
|
||||||
|
* @param fastify Optional Fastify instance to get Privy client
|
||||||
|
* @returns The wallet ID
|
||||||
|
*/
|
||||||
|
export const getWalletIdFromAddress = async (address: string, fastify?: FastifyInstance): Promise<string> => {
|
||||||
|
// Get user by wallet address - the response already contains wallet info in linked_accounts
|
||||||
|
const privy = getPrivyClient(fastify);
|
||||||
|
const user = await privy.users().getByWalletAddress({ address: address });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new Error(`User not found for wallet address: ${address}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the wallet matching the address in linked_accounts
|
||||||
|
const wallet = user.linked_accounts.find(
|
||||||
|
(account: any) =>
|
||||||
|
account.type === 'wallet' &&
|
||||||
|
account.chain_type === 'ethereum' &&
|
||||||
|
account.address?.toLowerCase() === address.toLowerCase()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!wallet) {
|
||||||
|
throw new Error(`Wallet not found for address ${address} in user's linked accounts`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the wallet ID directly from linked_accounts
|
||||||
|
// The wallet object has an 'id' field that contains the wallet ID
|
||||||
|
const walletId = (wallet as any).id;
|
||||||
|
if (!walletId) {
|
||||||
|
throw new Error(`Wallet ID not found in linked account for address ${address}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return walletId;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the chain name based on chain ID
|
* Gets the chain name based on chain ID
|
||||||
* @param chainId The chain ID
|
* @param chainId The chain ID
|
||||||
@@ -317,8 +354,11 @@ export const signMessage = async (walletId: string, message: string, address: st
|
|||||||
|
|
||||||
const authorizationContext = getAuthorizationContext(fastify);
|
const authorizationContext = getAuthorizationContext(fastify);
|
||||||
|
|
||||||
|
// Get wallet ID from address if not provided
|
||||||
|
const resolvedWalletId = walletId || await getWalletIdFromAddress(address, fastify);
|
||||||
|
|
||||||
const {signature} = await privy.wallets().ethereum().signMessage(
|
const {signature} = await privy.wallets().ethereum().signMessage(
|
||||||
address,
|
resolvedWalletId,
|
||||||
{
|
{
|
||||||
message: message,
|
message: message,
|
||||||
authorization_context: authorizationContext
|
authorization_context: authorizationContext
|
||||||
@@ -372,9 +412,12 @@ export const approveTokenImpl = async (
|
|||||||
const privy = getPrivyClient(fastify);
|
const privy = getPrivyClient(fastify);
|
||||||
const authorizationContext = getAuthorizationContext(fastify);
|
const authorizationContext = getAuthorizationContext(fastify);
|
||||||
|
|
||||||
|
// Get wallet ID from address
|
||||||
|
const walletId = await getWalletIdFromAddress(walletAddress, fastify);
|
||||||
|
|
||||||
// Send the transaction
|
// Send the transaction
|
||||||
const { hash } = await privy.wallets().ethereum().sendTransaction(
|
const { hash } = await privy.wallets().ethereum().sendTransaction(
|
||||||
walletAddress as Address,
|
walletId,
|
||||||
{
|
{
|
||||||
caip2: networkName as string,
|
caip2: networkName as string,
|
||||||
params: {
|
params: {
|
||||||
@@ -528,9 +571,12 @@ export const approveContractImpl = async (
|
|||||||
const privy = getPrivyClient(fastify);
|
const privy = getPrivyClient(fastify);
|
||||||
const authorizationContext = getAuthorizationContext(fastify);
|
const authorizationContext = getAuthorizationContext(fastify);
|
||||||
|
|
||||||
|
// Get wallet ID from address
|
||||||
|
const walletId = await getWalletIdFromAddress(walletAddress, fastify);
|
||||||
|
|
||||||
// Send the transaction
|
// Send the transaction
|
||||||
const { hash } = await privy.wallets().ethereum().sendTransaction(
|
const { hash } = await privy.wallets().ethereum().sendTransaction(
|
||||||
walletAddress as Address,
|
walletId,
|
||||||
{
|
{
|
||||||
caip2: networkName as string,
|
caip2: networkName as string,
|
||||||
params: {
|
params: {
|
||||||
@@ -963,11 +1009,12 @@ export const sendTokenImpl = async (
|
|||||||
const amountInSmallestUnit = Math.floor(amountFloat * Math.pow(10, tokenDecimals));
|
const amountInSmallestUnit = Math.floor(amountFloat * Math.pow(10, tokenDecimals));
|
||||||
|
|
||||||
const amountBigInt = BigInt(amountInSmallestUnit);
|
const amountBigInt = BigInt(amountInSmallestUnit);
|
||||||
|
const walletId = await getWalletIdFromAddress(senderAddress, fastify);
|
||||||
|
|
||||||
if (ticker === 'ETH') {
|
if (ticker === 'ETH') {
|
||||||
// Native ETH transfer: no allowance, no data, value is amount as hex string
|
// Native ETH transfer: no allowance, no data, value is amount as hex string
|
||||||
const { hash } = await privy.wallets().ethereum().sendTransaction(
|
const { hash } = await privy.wallets().ethereum().sendTransaction(
|
||||||
senderAddress as Address,
|
walletId,
|
||||||
{
|
{
|
||||||
caip2: networkName as string,
|
caip2: networkName as string,
|
||||||
params: {
|
params: {
|
||||||
@@ -1011,9 +1058,12 @@ export const sendTokenImpl = async (
|
|||||||
const transferAmount = amountBigInt;
|
const transferAmount = amountBigInt;
|
||||||
// Encode the transfer function call
|
// Encode the transfer function call
|
||||||
const data = contractInterface.encodeFunctionData("transfer", [recipientAddress, transferAmount]);
|
const data = contractInterface.encodeFunctionData("transfer", [recipientAddress, transferAmount]);
|
||||||
|
|
||||||
|
// Get wallet ID from address
|
||||||
|
|
||||||
// Send the transaction
|
// Send the transaction
|
||||||
const { hash } = await privy.wallets().ethereum().sendTransaction(
|
const { hash } = await privy.wallets().ethereum().sendTransaction(
|
||||||
senderAddress as Address,
|
walletId,
|
||||||
{
|
{
|
||||||
caip2: networkName as string,
|
caip2: networkName as string,
|
||||||
params: {
|
params: {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import {test} from 'node:test'
|
import {test} from 'node:test'
|
||||||
import assert from 'node:assert'
|
import assert from 'node:assert'
|
||||||
import {closeGmxPositionImpl, getClientForAddress} from '../../src/plugins/custom/gmx'
|
import {closeGmxPositionImpl, getClientForAddress} from '../../src/plugins/custom/gmx'
|
||||||
import {TradeDirection} from '../../src/generated/ManagingApiTypes'
|
import {Ticker, TradeDirection} from '../../src/generated/ManagingApiTypes'
|
||||||
|
|
||||||
test('GMX Position Closing', async (t) => {
|
test('GMX Position Closing', async (t) => {
|
||||||
await t.test('should close position', async () => {
|
await t.test('should close position', async () => {
|
||||||
const sdk = await getClientForAddress('0x1aDD85ee6f327d20340A451A8210FB32c4c97504')
|
const sdk = await getClientForAddress('0x932167388dD9aad41149b3cA23eBD489E2E2DD78')
|
||||||
|
|
||||||
const result = await closeGmxPositionImpl(
|
const result = await closeGmxPositionImpl(
|
||||||
sdk,
|
sdk,
|
||||||
"XRP",
|
Ticker.BTC,
|
||||||
TradeDirection.Long
|
TradeDirection.Long
|
||||||
)
|
)
|
||||||
console.log('Position closing result:', result)
|
console.log('Position closing result:', result)
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ test('GMX Position Opening', async (t) => {
|
|||||||
0.00012, // ~5.3 USDC collateral with 2x leverage (fits available balance of 5.69 USDC)
|
0.00012, // ~5.3 USDC collateral with 2x leverage (fits available balance of 5.69 USDC)
|
||||||
2,
|
2,
|
||||||
87856,
|
87856,
|
||||||
undefined, // No stop-loss
|
75000,
|
||||||
undefined // No take-profit
|
100000
|
||||||
)
|
)
|
||||||
console.log('Position opening result:', result)
|
console.log('Position opening result:', result)
|
||||||
assert.ok(result, 'Position opening result should be defined')
|
assert.ok(result, 'Position opening result should be defined')
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ describe('swap tokens implementation', () => {
|
|||||||
it('should swap SOL to USDC successfully', async () => {
|
it('should swap SOL to USDC successfully', async () => {
|
||||||
try {
|
try {
|
||||||
const testAccount = '0x932167388dD9aad41149b3cA23eBD489E2E2DD78'
|
const testAccount = '0x932167388dD9aad41149b3cA23eBD489E2E2DD78'
|
||||||
|
|
||||||
const sdk = await getClientForAddress(testAccount)
|
const sdk = await getClientForAddress(testAccount)
|
||||||
|
|
||||||
console.log('Account', sdk.account)
|
const result = await swapGmxTokensImpl(
|
||||||
const result = await swapGmxTokensImpl(
|
sdk,
|
||||||
sdk,
|
Ticker.SOL,
|
||||||
Ticker.USDC,
|
Ticker.USDC,
|
||||||
Ticker.SOL,
|
0.0495,
|
||||||
3,
|
'market',
|
||||||
'market',
|
undefined,
|
||||||
undefined,
|
0.5
|
||||||
0.5
|
)
|
||||||
)
|
|
||||||
|
|
||||||
assert.strictEqual(typeof result, 'string')
|
assert.strictEqual(typeof result, 'string')
|
||||||
assert.strictEqual(result, 'swap_order_created')
|
assert.strictEqual(result, 'swap_order_created')
|
||||||
|
|||||||
Reference in New Issue
Block a user