From 95e60108afa48b2a606cc5841010786f5a61f8e1 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Tue, 30 Dec 2025 03:02:23 +0700 Subject: [PATCH] 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. --- .../generated/gmxsdk/utils/callContract.ts | 10 ++- .../src/plugins/custom/privy.ts | 62 +++++++++++++++++-- .../test/plugins/close-position.test.ts | 6 +- .../test/plugins/open-position.test.ts | 4 +- .../test/plugins/swap-tokens.test.ts | 20 +++--- 5 files changed, 75 insertions(+), 27 deletions(-) diff --git a/src/Managing.Web3Proxy/src/generated/gmxsdk/utils/callContract.ts b/src/Managing.Web3Proxy/src/generated/gmxsdk/utils/callContract.ts index f788da56..6b14ebd9 100644 --- a/src/Managing.Web3Proxy/src/generated/gmxsdk/utils/callContract.ts +++ b/src/Managing.Web3Proxy/src/generated/gmxsdk/utils/callContract.ts @@ -1,5 +1,5 @@ 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 {bigMath} from "./bigmath.js"; @@ -125,6 +125,7 @@ export async function getGasLimit( export interface CallContractOpts { value?: bigint | number; gasLimit?: bigint | number; + did?: string; // Privy DID (user_id) to filter wallets } export async function callContract( @@ -236,13 +237,10 @@ export async function callContract( console.log('Method', method) console.log('Params', params) - const wallets = await privy.wallets().list(); - console.log('Wallets', wallets) - const currentWallet = wallets.data.find((wallet: any) => wallet.address === sdk.config.account); - console.log('walletId', currentWallet) + const walletId = await getWalletIdFromAddress(sdk.config.account); const response = await privy.wallets().ethereum().sendTransaction( - currentWallet.id, + walletId, { caip2: networkName, params: { diff --git a/src/Managing.Web3Proxy/src/plugins/custom/privy.ts b/src/Managing.Web3Proxy/src/plugins/custom/privy.ts index 3bd2d341..238b8781 100644 --- a/src/Managing.Web3Proxy/src/plugins/custom/privy.ts +++ b/src/Managing.Web3Proxy/src/plugins/custom/privy.ts @@ -14,7 +14,6 @@ import {getClientForAddress, getTokenDataFromTicker} from './gmx.js' import {Address, erc20Abi} from 'viem' import {Balance, Chain, Ticker} from '../../generated/ManagingApiTypes.js' import {getCachedPrivySecrets} from './privy-secrets.js' -import Token from '../../generated/gmxsdk/abis/Token.js' // Load environment variables in non-production only 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 => { + // 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 * @param chainId The chain ID @@ -317,8 +354,11 @@ export const signMessage = async (walletId: string, message: string, address: st 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( - address, + resolvedWalletId, { message: message, authorization_context: authorizationContext @@ -372,9 +412,12 @@ export const approveTokenImpl = async ( const privy = getPrivyClient(fastify); const authorizationContext = getAuthorizationContext(fastify); + // Get wallet ID from address + const walletId = await getWalletIdFromAddress(walletAddress, fastify); + // Send the transaction const { hash } = await privy.wallets().ethereum().sendTransaction( - walletAddress as Address, + walletId, { caip2: networkName as string, params: { @@ -528,9 +571,12 @@ export const approveContractImpl = async ( const privy = getPrivyClient(fastify); const authorizationContext = getAuthorizationContext(fastify); + // Get wallet ID from address + const walletId = await getWalletIdFromAddress(walletAddress, fastify); + // Send the transaction const { hash } = await privy.wallets().ethereum().sendTransaction( - walletAddress as Address, + walletId, { caip2: networkName as string, params: { @@ -963,11 +1009,12 @@ export const sendTokenImpl = async ( const amountInSmallestUnit = Math.floor(amountFloat * Math.pow(10, tokenDecimals)); const amountBigInt = BigInt(amountInSmallestUnit); + const walletId = await getWalletIdFromAddress(senderAddress, fastify); if (ticker === 'ETH') { // Native ETH transfer: no allowance, no data, value is amount as hex string const { hash } = await privy.wallets().ethereum().sendTransaction( - senderAddress as Address, + walletId, { caip2: networkName as string, params: { @@ -1011,9 +1058,12 @@ export const sendTokenImpl = async ( const transferAmount = amountBigInt; // Encode the transfer function call const data = contractInterface.encodeFunctionData("transfer", [recipientAddress, transferAmount]); + + // Get wallet ID from address + // Send the transaction const { hash } = await privy.wallets().ethereum().sendTransaction( - senderAddress as Address, + walletId, { caip2: networkName as string, params: { diff --git a/src/Managing.Web3Proxy/test/plugins/close-position.test.ts b/src/Managing.Web3Proxy/test/plugins/close-position.test.ts index ea5c8838..a7d65163 100644 --- a/src/Managing.Web3Proxy/test/plugins/close-position.test.ts +++ b/src/Managing.Web3Proxy/test/plugins/close-position.test.ts @@ -1,15 +1,15 @@ import {test} from 'node:test' import assert from 'node:assert' 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) => { await t.test('should close position', async () => { - const sdk = await getClientForAddress('0x1aDD85ee6f327d20340A451A8210FB32c4c97504') + const sdk = await getClientForAddress('0x932167388dD9aad41149b3cA23eBD489E2E2DD78') const result = await closeGmxPositionImpl( sdk, - "XRP", + Ticker.BTC, TradeDirection.Long ) console.log('Position closing result:', result) diff --git a/src/Managing.Web3Proxy/test/plugins/open-position.test.ts b/src/Managing.Web3Proxy/test/plugins/open-position.test.ts index 84aeb543..3b335ea2 100644 --- a/src/Managing.Web3Proxy/test/plugins/open-position.test.ts +++ b/src/Managing.Web3Proxy/test/plugins/open-position.test.ts @@ -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) 2, 87856, - undefined, // No stop-loss - undefined // No take-profit + 75000, + 100000 ) console.log('Position opening result:', result) assert.ok(result, 'Position opening result should be defined') diff --git a/src/Managing.Web3Proxy/test/plugins/swap-tokens.test.ts b/src/Managing.Web3Proxy/test/plugins/swap-tokens.test.ts index fa192f28..595950aa 100644 --- a/src/Managing.Web3Proxy/test/plugins/swap-tokens.test.ts +++ b/src/Managing.Web3Proxy/test/plugins/swap-tokens.test.ts @@ -8,18 +8,18 @@ describe('swap tokens implementation', () => { it('should swap SOL to USDC successfully', async () => { try { const testAccount = '0x932167388dD9aad41149b3cA23eBD489E2E2DD78' + const sdk = await getClientForAddress(testAccount) - console.log('Account', sdk.account) - const result = await swapGmxTokensImpl( - sdk, - Ticker.USDC, - Ticker.SOL, - 3, - 'market', - undefined, - 0.5 - ) + const result = await swapGmxTokensImpl( + sdk, + Ticker.SOL, + Ticker.USDC, + 0.0495, + 'market', + undefined, + 0.5 + ) assert.strictEqual(typeof result, 'string') assert.strictEqual(result, 'swap_order_created')