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:
2025-12-30 03:02:23 +07:00
parent 274effc749
commit 95e60108af
5 changed files with 75 additions and 27 deletions

View File

@@ -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: {

View File

@@ -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<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
* @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: {

View File

@@ -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)

View File

@@ -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')

View File

@@ -8,14 +8,14 @@ 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,
Ticker.USDC,
0.0495,
'market',
undefined,
0.5