mirror of
https://github.com/mempool/mempool.git
synced 2025-03-15 12:20:28 +01:00
move custom wallet sync to services backend
This commit is contained in:
parent
3f8eb3a2cd
commit
54c2d7efe5
2 changed files with 19 additions and 26 deletions
|
@ -9,55 +9,52 @@ interface WalletAddress {
|
||||||
address: string;
|
address: string;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
transactions?: IEsploraApi.AddressTxSummary[];
|
transactions?: IEsploraApi.AddressTxSummary[];
|
||||||
|
lastSync: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WalletConfig {
|
interface Wallet {
|
||||||
url: string;
|
|
||||||
name: string;
|
name: string;
|
||||||
apiKey: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Wallet extends WalletConfig {
|
|
||||||
addresses: Record<string, WalletAddress>;
|
addresses: Record<string, WalletAddress>;
|
||||||
lastPoll: number;
|
lastPoll: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const POLL_FREQUENCY = 60 * 60 * 1000; // 1 hour
|
const POLL_FREQUENCY = 5 * 60 * 1000; // 5 minutes
|
||||||
|
|
||||||
class WalletApi {
|
class WalletApi {
|
||||||
private wallets: Record<string, Wallet> = {};
|
private wallets: Record<string, Wallet> = {};
|
||||||
private syncing = false;
|
private syncing = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.wallets = (config.WALLETS.WALLETS as WalletConfig[]).reduce((acc, wallet) => {
|
this.wallets = config.WALLETS.ENABLED ? (config.WALLETS.WALLETS as string[]).reduce((acc, wallet) => {
|
||||||
acc[wallet.name] = { ...wallet, addresses: {}, lastPoll: 0 };
|
acc[wallet] = { name: wallet, addresses: {}, lastPoll: 0 };
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as Record<string, Wallet>);
|
}, {} as Record<string, Wallet>) : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
public getWallet(wallet: string): Record<string, WalletAddress> {
|
public getWallet(wallet: string): Record<string, WalletAddress> {
|
||||||
return this.wallets?.[wallet]?.addresses || {};
|
return this.wallets?.[wallet]?.addresses || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// resync wallet addresses from the provided API
|
// resync wallet addresses from the services backend
|
||||||
async $syncWallets(): Promise<void> {
|
async $syncWallets(): Promise<void> {
|
||||||
|
if (!config.WALLETS.ENABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.syncing = true;
|
this.syncing = true;
|
||||||
for (const walletKey of Object.keys(this.wallets)) {
|
for (const walletKey of Object.keys(this.wallets)) {
|
||||||
const wallet = this.wallets[walletKey];
|
const wallet = this.wallets[walletKey];
|
||||||
if (wallet.lastPoll < (Date.now() - POLL_FREQUENCY)) {
|
if (wallet.lastPoll < (Date.now() - POLL_FREQUENCY)) {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`${wallet.url}/${wallet.name}`, { headers: { 'Authorization': `${wallet.apiKey}` } });
|
const response = await axios.get(config.MEMPOOL_SERVICES.API + `/wallets/${wallet.name}`);
|
||||||
const data: { walletBalances: WalletAddress[] } = response.data;
|
const addresses: Record<string, WalletAddress> = response.data;
|
||||||
const addresses = data.walletBalances;
|
const addressList: WalletAddress[] = Object.values(addresses);
|
||||||
const newAddresses: Record<string, boolean> = {};
|
|
||||||
// sync all current addresses
|
// sync all current addresses
|
||||||
for (const address of addresses) {
|
for (const address of addressList) {
|
||||||
await this.$syncWalletAddress(wallet, address);
|
await this.$syncWalletAddress(wallet, address);
|
||||||
newAddresses[address.address] = true;
|
|
||||||
}
|
}
|
||||||
// remove old addresses
|
// remove old addresses
|
||||||
for (const address of Object.keys(wallet.addresses)) {
|
for (const address of Object.keys(wallet.addresses)) {
|
||||||
if (!newAddresses[address]) {
|
if (!addresses[address]) {
|
||||||
delete wallet.addresses[address];
|
delete wallet.addresses[address];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,16 +70,16 @@ class WalletApi {
|
||||||
|
|
||||||
// resync address transactions from esplora
|
// resync address transactions from esplora
|
||||||
async $syncWalletAddress(wallet: Wallet, address: WalletAddress): Promise<void> {
|
async $syncWalletAddress(wallet: Wallet, address: WalletAddress): Promise<void> {
|
||||||
// fetch full transaction data if the address is new or still active
|
// fetch full transaction data if the address is new or still active and hasn't been synced in the last hour
|
||||||
const refreshTransactions = !wallet.addresses[address.address] || address.active;
|
const refreshTransactions = !wallet.addresses[address.address] || (address.active && (Date.now() - wallet.addresses[address.address].lastSync) > 60 * 60 * 1000);
|
||||||
if (refreshTransactions) {
|
if (refreshTransactions) {
|
||||||
try {
|
try {
|
||||||
const walletAddress: WalletAddress = {
|
const walletAddress: WalletAddress = {
|
||||||
address: address.address,
|
address: address.address,
|
||||||
active: address.active,
|
active: address.active,
|
||||||
transactions: await bitcoinApi.$getAddressTransactionSummary(address.address),
|
transactions: await bitcoinApi.$getAddressTransactionSummary(address.address),
|
||||||
|
lastSync: Date.now(),
|
||||||
};
|
};
|
||||||
logger.debug(`Synced ${walletAddress.transactions?.length || 0} transactions for wallet ${wallet.name} address ${address.address}`);
|
|
||||||
wallet.addresses[address.address] = walletAddress;
|
wallet.addresses[address.address] = walletAddress;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.err(`Error syncing wallet address ${address.address}: ${(e instanceof Error ? e.message : e)}`);
|
logger.err(`Error syncing wallet address ${address.address}: ${(e instanceof Error ? e.message : e)}`);
|
||||||
|
|
|
@ -164,11 +164,7 @@ interface IConfig {
|
||||||
},
|
},
|
||||||
WALLETS: {
|
WALLETS: {
|
||||||
ENABLED: boolean;
|
ENABLED: boolean;
|
||||||
WALLETS: {
|
WALLETS: string[];
|
||||||
url: string;
|
|
||||||
name: string;
|
|
||||||
apiKey: string;
|
|
||||||
}[];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue