Skip to content

Commit

Permalink
Support List Historical Staking Balances
Browse files Browse the repository at this point in the history
List staking balances
  • Loading branch information
marchsu authored Aug 13, 2024
2 parents e38d836 + 10ba61c commit bc0e7f4
Show file tree
Hide file tree
Showing 14 changed files with 783 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Added

- Add Function `listHistoricalBalances` for `Address` for fetching historical balances for an asset
- Support for retrieving historical staking balances information

## [0.0.15]

Expand Down
161 changes: 161 additions & 0 deletions src/client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,31 @@ export interface FetchStakingRewardsRequest {
'format': StakingRewardFormat;
}

/**
*
* @export
* @interface FetchHistoricalStakingBalances200Response
*/
export interface FetchHistoricalStakingBalances200Response {
/**
*
* @type {Array<StakingBalance>}
* @memberof FetchHistoricalStakingBalances200Response
*/
'data': Array<StakingBalance>;
/**
* True if this list has another page of items after this one that can be fetched.
* @type {boolean}
* @memberof FetchHistoricalStakingBalances200Response
*/
'has_more': boolean;
/**
* The page token to be used to fetch the next page.
* @type {string}
* @memberof FetchHistoricalStakingBalances200Response
*/
'next_page': string;
}

/**
*
Expand Down Expand Up @@ -1381,6 +1406,44 @@ export interface StakingRewardUSDValue {
*/
'conversion_time': string;
}
/**
* The staking balances for an address.
* @export
* @interface StakingBalance
*/
export interface StakingBalance {
/**
* The onchain address for which the staking balances are being fetched.
* @type {string}
* @memberof StakingBalance
*/
'address': string;
/**
* The date of the staking balance in format \'YYYY-MM-DD\' in UTC.
* @type {string}
* @memberof StakingBalance
*/
'date': string;
/**
* The bonded stake.
* @type {Balance}
* @memberof StakingBalance
*/
'bonded_stake': Balance;
/**
* The unbonded balance.
* @type {Balance}
* @memberof StakingBalance
*/
'unbonded_balance': Balance;
/**
* The participant type of the given address.
* @type {string}
* @memberof StakingBalance
*/
'participant_type': string;
}

/**
* A trade of an asset to another asset
* @export
Expand Down Expand Up @@ -4110,6 +4173,69 @@ export const StakeApiAxiosParamCreator = function (configuration?: Configuration
options: localVarRequestOptions,
};
},
/**
* Fetch historical staking balances for a given address
* @summary Fetch historical staking balances
* @param {string} address The address to fetch the historical staking balances for
* @param {string} networkId The ID of the blockchain network
* @param {string} assetId The ID of the asset
* @param {string} startTime The start time of the staking balances period
* @param {string} endTime The end time of the stake balances period
* @param {number} [limit] A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 50.
* @param {string} [page] A cursor for pagination across multiple pages of results. Don\&#39;t include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
fetchHistoricalStakingBalances: async (address: string, networkId: string, assetId: string, startTime: string, endTime: string, limit?: number, page?: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'networkId' is not null or undefined
assertParamExists('fetchHistoricalStakingBalances', 'networkId', networkId)
// verify required parameter 'address' is not null or undefined
assertParamExists('fetchHistoricalStakingBalances', 'address', address)
// verify required parameter 'assetId' is not null or undefined
assertParamExists('fetchHistoricalStakingBalances', 'assetId', assetId)
// verify required parameter 'startTime' is not null or undefined
assertParamExists('fetchHistoricalStakingBalances', 'startTime', startTime)
// verify required parameter 'endTime' is not null or undefined
assertParamExists('fetchHistoricalStakingBalances', 'endTime', endTime)

const localVarPath = `/v1/networks/{network_id}/addresses/{address_id}/stake/balances`
.replace(`{${"network_id"}}`, encodeURIComponent(String(networkId)))
.replace(`{${"address_id"}}`, encodeURIComponent(String(address)))
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}

const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;

localVarQueryParameter['asset_id'] = assetId;
localVarQueryParameter['start_time'] = startTime;
localVarQueryParameter['end_time'] = endTime

if (limit !== undefined) {
localVarQueryParameter['limit'] = limit;
}

if (page !== undefined) {
localVarQueryParameter['page'] = page;
}

localVarHeaderParameter['Content-Type'] = 'application/json';

setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(null, localVarRequestOptions, configuration)

return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Get the latest state of a staking operation
* @summary Get the latest state of a staking operation
Expand Down Expand Up @@ -4299,6 +4425,25 @@ export const StakeApiFp = function(configuration?: Configuration) {
const localVarOperationServerBasePath = operationServerMap['StakeApi.fetchStakingRewards']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Fetch historical staking balances for given address
* @summary Fetch historical staking balances
* @param {string} address The address to fetch historical staking balances for
* @param {string} networkId The ID of the blockchain network
* @param {string} assetId The ID of the asset
* @param {string} startTime The start time of the staking balances
* @param {string} endTime The end time of the staking balances
* @param {number} [limit] A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 50.
* @param {string} [page] A cursor for pagination across multiple pages of results. Don\&#39;t include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async fetchHistoricalStakingBalances(address: string, networkId: string, assetId: string, startTime: string, endTime: string, limit?: number, page?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<FetchHistoricalStakingBalances200Response>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.fetchHistoricalStakingBalances(address, networkId, assetId, startTime, endTime, limit, page, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['StakeApi.fetchHistoricalStakingBalances']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Get the latest state of a staking operation
* @summary Get the latest state of a staking operation
Expand Down Expand Up @@ -4399,6 +4544,22 @@ export const StakeApiFactory = function (configuration?: Configuration, basePath
fetchStakingRewards(fetchStakingRewardsRequest: FetchStakingRewardsRequest, limit?: number, page?: string, options?: any): AxiosPromise<FetchStakingRewards200Response> {
return localVarFp.fetchStakingRewards(fetchStakingRewardsRequest, limit, page, options).then((request) => request(axios, basePath));
},
/**
* Fetch historical staking balances for given address
* @summary Fetch historical staking balances
* @param {string} address The onchain address for which the staking balances are being fetched
* @param {string} networkId The ID of the blockchain network
* @param {string} assetId The ID of the asset
* @param {string} startTime The start time of the staking balances period
* @param {string} endTime The end time of the staking balances period
* @param {number} [limit] A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 50.
* @param {string} [page] A cursor for pagination across multiple pages of results. Don\&#39;t include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
fetchHistoricalStakingBalances(address: string, networkId: string, assetId: string, startTime: string, endTime: string, limit?: number, page?: string, options?: any): AxiosPromise<FetchHistoricalStakingBalances200Response> {
return localVarFp.fetchHistoricalStakingBalances(address, networkId, assetId, startTime, endTime, limit, page, options).then((request) => request(axios, basePath));
},
/**
* Get the latest state of a staking operation
* @summary Get the latest state of a staking operation
Expand Down
23 changes: 23 additions & 0 deletions src/coinbase/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { formatDate, getWeekBackDate } from "./utils";
import { StakingRewardFormat } from "../client";
import { StakingReward } from "./staking_reward";
import { StakingBalance } from "./staking_balance";

/**
* A representation of a blockchain address, which is a user-controlled account on a network.
Expand Down Expand Up @@ -177,6 +178,28 @@ export class Address {
);
}

/**
* Lists the historical staking balances for the address.
*
* @param assetId - The asset ID.
* @param startTime - The start time.
* @param endTime - The end time.
* @returns The staking balances.
*/
public async historicalStakingBalances(
assetId: string,
startTime = getWeekBackDate(new Date()),
endTime = formatDate(new Date()),
): Promise<StakingBalance[]> {
return StakingBalance.list(
Coinbase.normalizeNetwork(this.getNetworkId()),
assetId,
this.getId(),
startTime,
endTime,
);
}

/**
* Get the stakeable balance for the supplied asset.
*
Expand Down
20 changes: 20 additions & 0 deletions src/coinbase/balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,24 @@ export class Balance {
asset,
);
}

/**
* Converts a BalanceModel of which the amount is in the most common denomination such as ETH, BTC, etc.
*
* @param {BalanceModel} model - The balance model object.
* @returns {Balance} The Balance object.
*/
public static fromModelWithAmountInWholeUnits(model: BalanceModel): Balance {
const asset = Asset.fromModel(model.asset);
return new Balance(new Decimal(model.amount), asset.getAssetId(), asset);
}

/**
* Print the Balance as a string.
*
* @returns The string representation of the Balance.
*/
public toString(): string {
return `Balance { amount: '${this.amount}' asset: '${this.asset?.toString()}' }`;
}
}
120 changes: 120 additions & 0 deletions src/coinbase/staking_balance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { StakingBalance as StakingBalanceModel } from "../client";
import { Balance } from "./balance";
import { Coinbase } from "./coinbase";

/**
* A representation of the staking balance for a given asset on a specific date.
*/
export class StakingBalance {
private model: StakingBalanceModel;

/**
* Creates the StakingBalance object.
*
* @param model - The underlying staking balance object.
*/
constructor(model: StakingBalanceModel) {
this.model = model;
}

/**
* Returns a list of StakingBalances for the provided network, asset, and address.
*
* @param networkId - The network ID.
* @param assetId - The asset ID.
* @param address - The address ID.
* @param startTime - The start time.
* @param endTime - The end time.
* @returns The staking balances.
*/
public static async list(
networkId: string,
assetId: string,
address: string,
startTime: string,
endTime: string,
): Promise<StakingBalance[]> {
const stakingBalances: StakingBalance[] = [];
const queue: string[] = [""];

while (queue.length > 0) {
const page = queue.shift();

const response = await Coinbase.apiClients.stake!.fetchHistoricalStakingBalances(
address,
networkId,
assetId,
startTime,
endTime,
100,
page?.length ? page : undefined,
);

response.data.data.forEach(stakingBalance => {
stakingBalances.push(new StakingBalance(stakingBalance));
});

if (response.data.has_more) {
if (response.data.next_page) {
queue.push(response.data.next_page);
}
}
}

return stakingBalances;
}

/**
* Returns the bonded stake amount of the StakingBalance.
*
* @returns The Balance.
*/
public bondedStake(): Balance {
return Balance.fromModelWithAmountInWholeUnits(this.model.bonded_stake);
}

/**
* Returns the unbonded stake amount of the StakingBalance.
*
* @returns The Balance.
*/
public unbondedBalance(): Balance {
return Balance.fromModelWithAmountInWholeUnits(this.model.unbonded_balance);
}

/**
* Returns the participant type of the address.
*
* @returns The participant type.
*/
public participantType(): string {
return this.model.participant_type;
}

/**
* Returns the date of the StakingBalance.
*
* @returns The date.
*/
public date(): Date {
return new Date(this.model.date);
}

/**
* Returns the onchain address of the StakingBalance.
*
* @returns The onchain address.
*/
public address(): string {
return this.model.address;
}

/**
* Print the Staking Balance as a string.
*
* @returns The string representation of the Staking Balance.
*/
public toString(): string {
return `StakingBalance { date: '${this.date().toISOString()}' address: '${this.address()}' bondedStake: '${this.bondedStake().toString()}' unbondedBalance: '${this.unbondedBalance().toString()}' participantType: '${this.participantType()}' }`;
}
}
Loading

0 comments on commit bc0e7f4

Please sign in to comment.