Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Pull balances /w block-height | fetch tokenPrice for native token #119

Merged
merged 30 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ebc15e7
Pull balances|Add opt block height /w fetching native balance
abhidtu2014 Nov 20, 2023
ec75a58
Add commitment in solana getBlockHeight
abhidtu2014 Nov 20, 2023
1890c8c
Refactor appending token balances in usd
abhidtu2014 Nov 20, 2023
dccaca9
Fix minor issue | fix type issue
abhidtu2014 Nov 20, 2023
65fb052
Bump with beta version
abhidtu2014 Nov 21, 2023
fa02da4
Make sure to compute tokenBalance in bigint
abhidtu2014 Nov 21, 2023
f26d81e
Refactor | Add usd balance for native tokens
abhidtu2014 Nov 23, 2023
d8c9754
Update code for all the chains
abhidtu2014 Nov 23, 2023
2d0b57e
Fix type issue
abhidtu2014 Nov 23, 2023
ac1b75a
Use number instead of bigint to avoid conversion issues
abhidtu2014 Nov 24, 2023
99b731c
Fix cache invalidation of token prices
abhidtu2014 Nov 24, 2023
64ced96
Accept blockHeightByChain as option in pullBalances method
abhidtu2014 Nov 24, 2023
ae5b0a9
Sync client wallet manager with wallet-manager changes
abhidtu2014 Nov 24, 2023
ec1212b
Fix Injecting native tokens logic
abhidtu2014 Nov 24, 2023
607b308
Lift priceFeedOptions as walletOptions
abhidtu2014 Nov 24, 2023
9020fe0
Optimize price feed instance instantiation
abhidtu2014 Nov 24, 2023
e21a2e1
Bump version
abhidtu2014 Nov 24, 2023
85af2ac
Add comment for wallet balance config
abhidtu2014 Nov 24, 2023
7c90d2e
Add chainName in balances schema
abhidtu2014 Nov 28, 2023
afa0653
Bump version
abhidtu2014 Nov 28, 2023
92e4ce5
minor update
abhidtu2014 Nov 28, 2023
2386304
publish beta version for integration
abhidtu2014 Nov 28, 2023
ed0112a
Revert mandatory blockHeight
abhidtu2014 Nov 28, 2023
fe3b028
Expose blockHeightPerChain method|remove chainName from balance
abhidtu2014 Nov 29, 2023
ba555ff
Bump package to latest version w.r.t main branch
abhidtu2014 Nov 29, 2023
3081d0c
Merge main branch
abhidtu2014 Nov 29, 2023
b9c8262
Resolve PR review comment
abhidtu2014 Dec 4, 2023
5c36e3e
Merge main branch
abhidtu2014 Dec 4, 2023
77fd30c
Add coingeckoIds for cosm-wasm chains
abhidtu2014 Dec 4, 2023
8ca519b
Bump version
abhidtu2014 Dec 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 49 additions & 14 deletions examples/wallet-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,42 @@ const allChainWallets: WalletManagerFullConfig['config'] = {
tokens: ["WBTC"]
}
],
priceFeedConfig: {
walletBalanceConfig: {
enabled: true,
scheduled: {
enabled: true
},
enabled: false,
}
},
priceFeedConfig: {
supportedTokens: [{
chainId: 2,
chainName: "ethereum",
tokenContract: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
coingeckoId: "usd-coin",
symbol: "USDC"
},
{
chainId: 2,
chainName: "ethereum",
tokenContract: "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
coingeckoId: "wrapped-bitcoin",
symbol: "WBTC"
}],
enabled: true
}
},
solana: {
wallets: [
{ address: "6VnfVsLdLwNuuCmooLTziQ99PFXZ5vc3yyqyb9tMDhhw", tokens: ['usdc'] },
],
walletBalanceConfig: {
enabled: true,
scheduled: {
enabled: false,
}
},
priceFeedConfig: {
supportedTokens: []
}
},
sui: {
rebalance: {
Expand All @@ -62,14 +75,20 @@ const allChainWallets: WalletManagerFullConfig['config'] = {
tokens: ['USDC', 'USDT']
},
],
walletBalanceConfig: {
enabled: true,
scheduled: {
enabled: false,
}
},
priceFeedConfig: {
supportedTokens: [{
chainId: 21,
chainName: "sui",
tokenContract: "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf",
coingeckoId: "usd-coin",
symbol: "USDC"
}],
enabled: false,
}
},
klatyn: {
Expand All @@ -88,7 +107,16 @@ const allChainWallets: WalletManagerFullConfig['config'] = {
address: "0x8d0d970225597085A59ADCcd7032113226C0419d",
tokens: []
}
]
],
walletBalanceConfig: {
enabled: true,
scheduled: {
enabled: false,
}
},
priceFeedConfig: {
supportedTokens: []
}
}
}

Expand All @@ -103,15 +131,22 @@ export const manager = buildWalletManager({
enabled: true,
serve: true,
port: 9091,
},
priceFeedOptions: {
enabled: true,
scheduled: {
enabled: false,
}
}
}
});


// Note: Below code needs wallet's private key to be set in config abopve for aquiring wallet
// manager.withWallet('ethereum', async (wallet) => {
// console.log('Address', wallet.address);
// console.log('Block height', wallet.walletToolbox.getBlockHeight());
// console.log('Native balances', await wallet.walletToolbox.pullNativeBalance(wallet.address));
// console.log('Token balances', await wallet.walletToolbox.pullTokenBalances(wallet.address, ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599']));
// })
(async () => {
try {
console.time('balances')
const balances = await manager.pullBalancesAtBlockHeight();
console.timeLog('balances', JSON.stringify(balances))
} catch (err) {
console.error('Failed to pullBalancesAtBlockHeight', err);
}
})();
5 changes: 3 additions & 2 deletions src/balances/evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ export async function pullEvmTokenBalance(
export async function pullEvmNativeBalance(
provider: ethers.providers.JsonRpcProvider,
address: string,
blockHeight?: number,
): Promise<Balance>{
const weiAmount = await provider.getBalance(address);
const weiAmount = await provider.getBalance(address, blockHeight);

return {
isNative: true,
rawBalance: weiAmount.toString(),
Expand Down
6 changes: 4 additions & 2 deletions src/balances/solana.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import bs58 from 'bs58';
import { Connection, PublicKey, Keypair } from "@solana/web3.js";
import { Balance } from "./index";
import { SOLANA_DEFAULT_COMMITMENT } from '../wallets/solana/solana.config';

export async function pullSolanaNativeBalance(
connection: Connection,
address: string
address: string,
): Promise<Balance> {
const lamports = await connection.getBalance(new PublicKey(address))
// solana web3.js doesn't support passing exact slot(block number) only minSlot, while fetching balance
const lamports = await connection.getBalance(new PublicKey(address), SOLANA_DEFAULT_COMMITMENT)

return {
isNative: true,
Expand Down
12 changes: 11 additions & 1 deletion src/balances/sui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface SuiTransactionDetails {
export async function pullSuiNativeBalance(conn: Connection, address: string): Promise<WalletBalance> {
const provider = new JsonRpcProvider(conn);

// mysten SDK doesn't support passing checkpoint (block number) to getBalance
// https://github.com/MystenLabs/sui/issues/14137
const rawBalance = await provider.getBalance({ owner: address });

return {
Expand Down Expand Up @@ -54,7 +56,15 @@ export async function pullSuiTokenData(
export async function pullSuiTokenBalances(
conn: Connection,
address: string
): Promise<any> {
): Promise<{
coinType: string;
coinObjectCount: number;
totalBalance: string;
lockedBalance: {
number?: number | undefined;
epochId?: number | undefined;
};
}[]> {
const provider = new JsonRpcProvider(conn);

return provider.getAllBalances({ owner: address });
Expand Down
57 changes: 37 additions & 20 deletions src/chain-wallet-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ import { CosmosProvider, CosmosWallet } from "./wallets/cosmos";
import { EVMProvider, EVMWallet } from "./wallets/evm";
import { SolanaProvider, SolanaWallet } from "./wallets/solana";
import { SuiProvider, SuiWallet } from "./wallets/sui";
import {
PriceFeed,
WalletPriceFeedConfig,
WalletRebalancingConfig,
} from "./wallet-manager";
import { ScheduledPriceFeed } from "./price-assistant/scheduled-price-feed";
import { OnDemandPriceFeed } from "./price-assistant/ondemand-price-feed";
import { PriceFeed, WalletBalanceConfig, WalletPriceFeedConfig, WalletRebalancingConfig } from "./wallet-manager";

const DEFAULT_POLL_INTERVAL = 60 * 1000;
const DEFAULT_REBALANCE_INTERVAL = 60 * 1000;
Expand All @@ -42,6 +36,7 @@ export type ChainWalletManagerOptions = {
maxGasPrice?: number;
gasLimit?: number;
};
walletBalanceConfig: WalletBalanceConfig;
priceFeedConfig: WalletPriceFeedConfig;
balancePollInterval?: number;
walletOptions?: WalletOptions;
Expand Down Expand Up @@ -85,7 +80,11 @@ export class ChainWalletManager {
public walletToolbox: Wallet;
protected priceFeed?: PriceFeed;

constructor(options: any, private wallets: WalletConfig[]) {
constructor(
options: any,
private wallets: WalletConfig[],
priceFeedInstance?: PriceFeed,
) {
this.validateOptions(options);
this.options = this.parseOptions(options);

Expand All @@ -94,15 +93,7 @@ export class ChainWalletManager {
}

this.logger = createLogger(this.options.logger);
const { priceFeedConfig } = this.options;

if (priceFeedConfig?.enabled) {
if (priceFeedConfig?.scheduled?.enabled) {
this.priceFeed = new ScheduledPriceFeed(priceFeedConfig, this.logger);
} else {
this.priceFeed = new OnDemandPriceFeed(priceFeedConfig, this.logger);
}
}
this.priceFeed = priceFeedInstance

this.walletToolbox = createWalletToolbox(
options.network,
Expand Down Expand Up @@ -274,9 +265,20 @@ export class ChainWalletManager {
);
this.priceFeed?.start();
}
this.interval = setInterval(async () => {
await this.refreshBalances();
}, this.options.balancePollInterval);

if (this.options.walletBalanceConfig?.enabled) {
if (this.options.walletBalanceConfig?.scheduled?.enabled) {
this.interval = setInterval(async () => {
await this.refreshBalances();
}, this.options.walletBalanceConfig?.scheduled?.interval ?? this.options.balancePollInterval);
} else {
// no op: Don't poll balances, fetch on demand instead
}
} else {
this.interval = setInterval(async () => {
await this.refreshBalances();
}, this.options.balancePollInterval);
}

if (this.options.rebalance.enabled) {
this.logger.info(
Expand Down Expand Up @@ -419,4 +421,19 @@ export class ChainWalletManager {
this.availableWalletsByChainName[chainName],
);
}

public getBlockHeight () {
return this.walletToolbox.getBlockHeight();
}
/** Pull balances on demand */
public async pullBalances () {
const balances = await this.walletToolbox.pullBalances();
return this.mapBalances(balances);
}

/** Pull balances on demand with block height */
public async pullBalancesAtBlockHeight(blockHeight: number) {
const balances = await this.walletToolbox.pullBalancesAtBlockHeight(blockHeight);
return this.mapBalances(balances);
}
}
Loading
Loading