Skip to content

Commit

Permalink
[accounts] Add nonce to AccountBalanceResponse metadata (#91)
Browse files Browse the repository at this point in the history
Co-authored-by: Dmitry Osipov <[email protected]>
  • Loading branch information
stefanmendoza-cb and osipov-mit authored Sep 13, 2023
1 parent 3fcd29b commit edc0671
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 103 deletions.
154 changes: 74 additions & 80 deletions client/src/model/AccountBalanceResponse.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Build Once. Integrate Your Blockchain Everywhere.
*
* The version of the OpenAPI document: 1.4.13
*
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
Expand All @@ -21,86 +21,86 @@ import BlockIdentifier from './BlockIdentifier';
* @version 1.4.13
*/
class AccountBalanceResponse {
/**
* Constructs a new <code>AccountBalanceResponse</code>.
* An AccountBalanceResponse is returned on the /account/balance endpoint. If an account has a balance for each AccountIdentifier describing it (ex: an ERC-20 token balance on a few smart contracts), an account balance request must be made with each AccountIdentifier. The &#x60;coins&#x60; field was removed and replaced by by &#x60;/account/coins&#x60; in &#x60;v1.4.7&#x60;.
* @alias module:model/AccountBalanceResponse
* @param blockIdentifier {module:model/BlockIdentifier}
* @param balances {Array.<module:model/Amount>} A single account may have a balance in multiple currencies.
*/
constructor(blockIdentifier, balances) {

AccountBalanceResponse.initialize(this, blockIdentifier, balances);
/**
* Constructs a new <code>AccountBalanceResponse</code>.
* An AccountBalanceResponse is returned on the /account/balance endpoint. If an account has a balance for each AccountIdentifier describing it (ex: an ERC-20 token balance on a few smart contracts), an account balance request must be made with each AccountIdentifier. The &#x60;coins&#x60; field was removed and replaced by by &#x60;/account/coins&#x60; in &#x60;v1.4.7&#x60;.
* @alias module:model/AccountBalanceResponse
* @param blockIdentifier {module:model/BlockIdentifier}
* @param balances {Array.<module:model/Amount>} A single account may have a balance in multiple currencies.
*/
constructor(blockIdentifier, balances, metadata) {
AccountBalanceResponse.initialize(this, blockIdentifier, balances, metadata);
}

/**
* Initializes the fields of this object.
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/
static initialize(obj, blockIdentifier, balances, metadata) {
obj['block_identifier'] = blockIdentifier;
obj['balances'] = balances;
obj['metadata'] = metadata;
}

/**
* Constructs a <code>AccountBalanceResponse</code> from a plain JavaScript object, optionally creating a new instance.
* Copies all relevant properties from <code>data</code> to <code>obj</code> if supplied or a new instance if not.
* @param {Object} data The plain JavaScript object bearing properties of interest.
* @param {module:model/AccountBalanceResponse} obj Optional instance to populate.
* @return {module:model/AccountBalanceResponse} The populated <code>AccountBalanceResponse</code> instance.
*/
static constructFromObject(data, obj) {
if (data) {
obj = obj || new AccountBalanceResponse();

if (data.hasOwnProperty('block_identifier')) {
obj['block_identifier'] = BlockIdentifier.constructFromObject(data['block_identifier']);
}
if (data.hasOwnProperty('balances')) {
obj['balances'] = ApiClient.convertToType(data['balances'], [Amount]);
}
if (data.hasOwnProperty('metadata')) {
obj['metadata'] = ApiClient.convertToType(data['metadata'], Object);
}
}

/**
* Initializes the fields of this object.
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/
static initialize(obj, blockIdentifier, balances) {
obj['block_identifier'] = blockIdentifier;
obj['balances'] = balances;
return obj;
}

/**
* Validates the JSON data with respect to <code>AccountBalanceResponse</code>.
* @param {Object} data The plain JavaScript object bearing properties of interest.
* @return {boolean} to indicate whether the JSON data is valid with respect to <code>AccountBalanceResponse</code>.
*/
static validateJSON(data) {
// check to make sure all required properties are present in the JSON string
for (const property of AccountBalanceResponse.RequiredProperties) {
if (!data[property]) {
throw new Error('The required field `' + property + '` is not found in the JSON data: ' + JSON.stringify(data));
}
}

/**
* Constructs a <code>AccountBalanceResponse</code> from a plain JavaScript object, optionally creating a new instance.
* Copies all relevant properties from <code>data</code> to <code>obj</code> if supplied or a new instance if not.
* @param {Object} data The plain JavaScript object bearing properties of interest.
* @param {module:model/AccountBalanceResponse} obj Optional instance to populate.
* @return {module:model/AccountBalanceResponse} The populated <code>AccountBalanceResponse</code> instance.
*/
static constructFromObject(data, obj) {
if (data) {
obj = obj || new AccountBalanceResponse();

if (data.hasOwnProperty('block_identifier')) {
obj['block_identifier'] = BlockIdentifier.constructFromObject(data['block_identifier']);
}
if (data.hasOwnProperty('balances')) {
obj['balances'] = ApiClient.convertToType(data['balances'], [Amount]);
}
if (data.hasOwnProperty('metadata')) {
obj['metadata'] = ApiClient.convertToType(data['metadata'], Object);
}
}
return obj;
// validate the optional field `block_identifier`
if (data['block_identifier']) {
// data not null
BlockIdentifier.validateJSON(data['block_identifier']);
}

/**
* Validates the JSON data with respect to <code>AccountBalanceResponse</code>.
* @param {Object} data The plain JavaScript object bearing properties of interest.
* @return {boolean} to indicate whether the JSON data is valid with respect to <code>AccountBalanceResponse</code>.
*/
static validateJSON(data) {
// check to make sure all required properties are present in the JSON string
for (const property of AccountBalanceResponse.RequiredProperties) {
if (!data[property]) {
throw new Error("The required field `" + property + "` is not found in the JSON data: " + JSON.stringify(data));
}
}
// validate the optional field `block_identifier`
if (data['block_identifier']) { // data not null
BlockIdentifier.validateJSON(data['block_identifier']);
}
if (data['balances']) { // data not null
// ensure the json data is an array
if (!Array.isArray(data['balances'])) {
throw new Error("Expected the field `balances` to be an array in the JSON data but got " + data['balances']);
}
// validate the optional field `balances` (array)
for (const item of data['balances']) {
Amount.validateJsonObject(item);
};
}

return true;
if (data['balances']) {
// data not null
// ensure the json data is an array
if (!Array.isArray(data['balances'])) {
throw new Error('Expected the field `balances` to be an array in the JSON data but got ' + data['balances']);
}
// validate the optional field `balances` (array)
for (const item of data['balances']) {
Amount.validateJsonObject(item);
}
}


return true;
}
}

AccountBalanceResponse.RequiredProperties = ["block_identifier", "balances"];
AccountBalanceResponse.RequiredProperties = ['block_identifier', 'balances'];

/**
* @member {module:model/BlockIdentifier} block_identifier
Expand All @@ -119,10 +119,4 @@ AccountBalanceResponse.prototype['balances'] = undefined;
*/
AccountBalanceResponse.prototype['metadata'] = undefined;






export default AccountBalanceResponse;

4 changes: 2 additions & 2 deletions client/types/model/AccountBalanceResponse.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ declare class AccountBalanceResponse {
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/
static initialize(obj: any, blockIdentifier: any, balances: any): void;
static initialize(obj: any, blockIdentifier: any, balances: Array<Amount>, metadata: any): void;
/**
* Constructs a <code>AccountBalanceResponse</code> from a plain JavaScript object, optionally creating a new instance.
* Copies all relevant properties from <code>data</code> to <code>obj</code> if supplied or a new instance if not.
Expand All @@ -34,7 +34,7 @@ declare class AccountBalanceResponse {
* @param blockIdentifier {module:model/BlockIdentifier}
* @param balances {Array.<module:model/Amount>} A single account may have a balance in multiple currencies.
*/
constructor(blockIdentifier: any, balances: Array<Amount>);
constructor(blockIdentifier: any, balances: Array<Amount>, metadata: any);
block_identifier: any;
balances: any;
metadata: any;
Expand Down
34 changes: 16 additions & 18 deletions server/src/helpers/gear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class GearApi {
this.api.on('connected', () => {
logger.info('Connected established!');
});

this.api.on('disconnected', () => {
logger.warn('Disconnected from node. Attempting to reconnect.');
this.connect();
Expand All @@ -42,13 +42,13 @@ export class GearApi {
this.api.on('error', (err: Error) => {
logger.error(
'An error occurred with the node connection. Sleeping for 60 seconds then attempting to reconnect.',
{ error: err }
{ error: err },
);
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
sleep(60000).then(this.connect);
});

this.genesis = this.api.genesisHash.toHex();
}

Expand All @@ -71,12 +71,8 @@ export class GearApi {

return { block, apiAt };
} catch (err) {
const errorMetadata = typeof at === 'string'
? { hash: at }
: typeof at === 'number'
? { index: at }
: undefined;

const errorMetadata = typeof at === 'string' ? { hash: at } : typeof at === 'number' ? { index: at } : undefined;

throwError(ApiError.UNABLE_TO_GET_BLOCK, errorMetadata, err);
}
}
Expand All @@ -91,12 +87,14 @@ export class GearApi {
return [new BlockIdentifier(blockIndex, blockHash), ts, block, apiAt];
}

async getBalanceAtBlock(address: string, blockHash: string): Promise<string> {
async getBalanceAtBlock(address: string, blockHash: string): Promise<{ balance: string; nonce: string }> {
const apiAt = await this.apiAt(blockHash);
const {
data: { free },
} = await apiAt.query.system.account(address);
return free.toString();
const accountData = await apiAt.query.system.account(address);

return {
balance: accountData.data.free.toString(),
nonce: accountData.nonce.toString(),
};
}

async getSigningInfo(pk: string) {
Expand All @@ -120,7 +118,7 @@ export class GearApi {
blockNumber,
eraPeriod,
specVersion,
transactionVersion
transactionVersion,
};
}

Expand All @@ -133,7 +131,7 @@ export class GearApi {
}

async syncState(): Promise<SyncStatus> {
let syncState = await this.api.rpc.system.syncState();
const syncState = await this.api.rpc.system.syncState();
const current_index = syncState.currentBlock.toNumber();
const target_index = syncState.highestBlock
.unwrapOr((await this.api.rpc.chain.getBlock()).block.header.number)
Expand Down
2 changes: 1 addition & 1 deletion server/src/helpers/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ export async function getOperations(

if (isBalanceSetEvent(event)) {
const acc = data[0].toString();
const balance = new BN(await api.getBalanceAtBlock(acc, parentBlockHash));
const balance = new BN(await api.getBalanceAtBlock(acc, parentBlockHash)['balance']);
const setBalanceAmount = (data[1] as u128).toBn();
const amount = setBalanceAmount.sub(balance).toString();

Expand Down
4 changes: 2 additions & 2 deletions server/src/services/AccountService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ const accountBalance = async ({ body: { account_identifier, network_identifier,
block_identifier ? (block_identifier.hash ? block_identifier.hash : block_identifier.index) : undefined,
);

const balance = await api.getBalanceAtBlock(account_identifier.address, blockIdent.hash);
const { balance, nonce } = await api.getBalanceAtBlock(account_identifier.address, blockIdent.hash);

return new AccountBalanceResponse(blockIdent, [new Amount(balance, currency)]);
return new AccountBalanceResponse(blockIdent, [new Amount(balance, currency)], { nonce: nonce });
};

const accountCoins = () => throwError(ApiError.NOT_SUPPORTED);
Expand Down

0 comments on commit edc0671

Please sign in to comment.