Coinbase API BTC帐户丢失



感谢您的帮助。在使用coinbase API的过程中,当我调用
client.getAccounts({}, function(error, accounts){
console.log('accounts', accounts)})
我注意到许多账户,包括以太坊、莱特币,但没有比特币(BTC(有人能帮我找出原因吗?非常感谢!

TL;DR

使用yarn add rxjsnpm install rxjsrxjs添加到您的项目中,然后执行以下操作:

import { EMPTY, from, reduce, expand } from 'rxjs';
// Promisify: Wrap API call in a promise
const getAccountsAsync = (options) => {
return new Promise((resolve, reject) => {
client.getAccounts(options, (err, accounts, pagination) => {
if (err) return reject(err);
resolve({accounts, pagination});
})
})
}
// Number of accounts to fetch per request
const paginationLimit = 100;
from(getAccountsAsync({limit: paginationLimit})).pipe(
// As long as there is a next_uri set, continue recursion
expand(res => res.pagination.next_uri ? 
getAccountsAsync({
limit: paginationLimit,
next_uri: res.pagination.next_uri, 
starting_after: res.pagination.next_starting_after
}) : 
EMPTY
),
// Filter and concatenate the result of all API calls
reduce((acc, current) => acc.concat(current.accounts.filter(account => account.balance.amount > 0)), [])
).subscribe(allAccounts => console.log(allAccounts));

解释

之所以只返回前25个帐户,是因为coinbase API使用分页,而25是默认的页面大小(请参阅官方文档(。

当您调用getAccounts()时,您实际上得到了三个返回值(即使API只指定了两个(:

client.getAccounts({}, (err, accounts, pagination) => {});

分页对象看起来像这样:

{
ending_before: null,
starting_after: null,
previous_ending_before: null,
next_starting_after: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
limit: 25,
order: 'desc',
previous_uri: null,
next_uri: '/v2/accounts?limit=25&starting_after=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
}

你可以这样增加限制:

client.getAccounts({limit: 100}, (err, accounts, pagination) => {});

然而,目前coinbase中有175个账户(货币(,我们可以提供的最大分页限制是100。

因此,为了获取其余的页面,我们必须进行额外的API调用,提供starting_afternext_uri作为选项,如下所示:

client.getAccounts({
limit: 100,
next_uri: '/v2/accounts?limit=100&starting_after=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
starting_after: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
}, (err, accounts, pagination) => {});

关于next_uri的旁注

在已经有starting_after的情况下,我们必须提供next_uri,这似乎是多余的。事实上,文件中并没有提到我们必须提供next_uri。然而,如果我忽略这个值,我会得到以下错误:

ClientError [AuthenticationError]: invalid signature

在深入研究源代码后,我发现在检查starting_after是否已设置之前,他们会检查next_uri是否已设置。因此,显然我们必须提供这种价值。

解决方案1-递归承诺

要打印所有帐户(其中balance.amount > 0的帐户(,我们可以首先将API调用包装在promise中,然后使用递归。一个可能的解决方案如下:

// Promisify: Wrap API call in a promise
const getAccountsAsync = (options) => {
return new Promise((resolve, reject) => {
client.getAccounts(options, (err, accounts, pagination) => {
if (err) return reject(err);
resolve({accounts, pagination});
})
})
}
// Fetch all accounts recursively 
const fetchAllAccounts = (nextUri, lastFetchedId) => {
getAccountsAsync({limit: 100, next_uri: nextUri, starting_after: lastFetchedId})
.then(res => {
// Print your accounts from current batch
res.accounts.forEach(account => {
if (account.balance.amount > 0) {
console.log(account)     
}
});

// Terminate recursion when next_uri is empty
if (res.pagination.next_uri != null) {
// Call next batch of 100 accounts, starting after lastFetchedId
fetchAllAccounts(res.pagination.next_uri, res.pagination.next_starting_after)
}
})
.catch(err => console.log(err));
};
// Initial call
fetchAllAccounts(null, null);

不幸的是,使用这种方法,帐户分布在多个回调中。我们不能轻易地与他们合作。如果你想对你的账户做更多的事情,而不仅仅是把它们打印到控制台上,你可以使用RxJS。

解决方案2-使用RxJS

更优雅的解决方案是使用RxJS中的expand函数。同样,我们必须首先将API调用封装在promise中。

使用yarn add rxjsnpm install rxjsrxjs添加到您的项目中,然后执行以下操作:

import { EMPTY, from, reduce, expand } from 'rxjs';
// Promisify: Wrap API call in a promise
const getAccountsAsync = (options) => {
return new Promise((resolve, reject) => {
client.getAccounts(options, (err, accounts, pagination) => {
if (err) return reject(err);
resolve({accounts, pagination});
})
})
}
// Number of accounts to fetch per request
const paginationLimit = 100;
from(getAccountsAsync({limit: paginationLimit})).pipe(
// As long as there is a next_uri set, continue recursion
expand(res => res.pagination.next_uri ? 
getAccountsAsync({
limit: paginationLimit,
next_uri: res.pagination.next_uri, 
starting_after: res.pagination.next_starting_after
}) : 
EMPTY
),
// Filter and concatenate the result of all API calls
reduce((acc, current) => acc.concat(current.accounts.filter(account => account.balance.amount > 0)), [])
).subscribe(allAccounts => console.log(allAccounts));

这种方法的优点是,我们可以将所有API调用的结果连接起来,并将它们组合到一个数组中。

由于某种原因,比特币不在返回的主账户中。您可以使用此调用获取特定帐户。
btcAccount = client.get_account('BTC')

最新更新