UNPKG

@substrate/api-sidecar

Version:

REST service that makes it easy to interact with blockchain nodes built using Substrate's FRAME framework.

184 lines 7.79 kB
"use strict"; // Copyright 2017-2025 Parity Technologies (UK) Ltd. // This file is part of Substrate API Sidecar. // // Substrate API Sidecar is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. Object.defineProperty(exports, "__esModule", { value: true }); exports.AccountsPoolAssetsService = void 0; const http_errors_1 = require("http-errors"); const AbstractService_1 = require("../AbstractService"); class AccountsPoolAssetsService extends AbstractService_1.AbstractService { /** * Fetch all the `PoolAssetBalance`s alongside their `AssetId`'s for a given array of queried `AssetId`'s. * If none are queried the function will get all `AssetId`'s associated with the * given `AccountId`, and send back all the `PoolAssetsBalance`s. * * @param hash `BlockHash` to make call at * @param address `AccountId` associated with the balances * @param assets An array of `assetId`'s to be queried. If the length is zero * all assetId's associated to the account will be queried */ async fetchPoolAssetBalances(hash, address, assets) { const { api } = this; const [historicApi, { number }] = await Promise.all([api.at(hash), api.rpc.chain.getHeader(hash)]); // Check if this runtime has the PoolAssets pallet this.checkPoolAssetsError(historicApi); let response; if (assets.length === 0) { /** * This will query all pool assets and return them in an array */ const keys = await historicApi.query.poolAssets.asset.keys(); const assetIds = this.extractPoolAssetIds(keys); response = await this.queryPoolAssets(historicApi, assetIds, address); } else { /** * This will query all pool assets by the requested AssetIds */ response = await this.queryPoolAssets(historicApi, assets, address); } const at = { hash, height: number.unwrap().toString(10), }; return { at, poolAssets: response, }; } /** * Fetch all `AccountApproval`'s with a given `AssetId` and a `AssetApprovalKey` * which consists of a `delegate` and an `owner` * * @param hash `BlockHash` to make call at * @param address `AccountId` or owner associated with the approvals * @param assetId `AssetId` associated with the `AssetApproval` * @param delegate `delegate` */ async fetchPoolAssetApprovals(hash, address, assetId, delegate) { const { api } = this; const historicApi = await api.at(hash); // Check if this runtime has the assets pallet this.checkPoolAssetsError(historicApi); const [{ number }, assetApproval] = await Promise.all([ api.rpc.chain.getHeader(hash), historicApi.query.poolAssets.approvals(assetId, address, delegate), ]).catch((err) => { throw this.createHttpErrorForAddr(address, err); }); let amount = null, deposit = null; if (assetApproval.isSome) { ({ amount, deposit } = assetApproval.unwrap()); } const at = { hash, height: number.unwrap().toString(10), }; return { at, amount, deposit, }; } /** * Takes in an array of `AssetId`s, and an `AccountId` and returns * all balances tied to those `AssetId`s. * * @param api ApiPromise * @param assets An Array of `AssetId`s or numbers representing `assetId`s * @param address An `AccountId` associated with the queried path */ async queryPoolAssets(historicApi, assets, address) { return Promise.all(assets.map(async (assetId) => { const assetBalance = await historicApi.query.poolAssets.account(assetId, address); /** * The following checks for three different cases: */ // 1. Via runtime v9160 the updated storage introduces a `reason` field, // and polkadot-js wraps the newly returned `PalletAssetsAssetAccount` in an `Option`. if (assetBalance.isSome) { const balanceProps = assetBalance.unwrap(); let isFrozen; if ('isFrozen' in balanceProps) { isFrozen = balanceProps.isFrozen; } else { isFrozen = 'isFrozen does not exist for this runtime'; } return { assetId, balance: balanceProps.balance, isFrozen: isFrozen, isSufficient: balanceProps.reason.isSufficient, }; } // 2. `query.assets.account()` return `PalletAssetsAssetBalance` which exludes `reasons` but has // `sufficient` as a key. if (assetBalance.sufficient) { const balanceProps = assetBalance; return { assetId, balance: balanceProps.balance, isFrozen: balanceProps.isFrozen, isSufficient: balanceProps.sufficient, }; } // 3. The older legacy type of `PalletAssetsAssetBalance` has a key of `isSufficient` instead // of `sufficient`. if (assetBalance.isSufficient) { const balanceProps = assetBalance; return { assetId, balance: balanceProps.balance, isFrozen: balanceProps.isFrozen, isSufficient: balanceProps.isSufficient, }; } /** * This return value wont ever be reached as polkadot-js defaults the * `balance` value to `0`, `isFrozen` to false, and `isSufficient` to false. * This ensures that the typescript compiler is happy, but we also follow along * with polkadot-js/substrate convention. */ return { assetId, balance: historicApi.registry.createType('u128', 0), isFrozen: historicApi.registry.createType('bool', false), isSufficient: historicApi.registry.createType('bool', false), }; })).catch((err) => { throw this.createHttpErrorForAddr(address, err); }); } /** * @param keys Extract `assetId`s from an array of storage keys */ extractPoolAssetIds(keys) { return keys.map(({ args: [assetId] }) => assetId); } /** * Checks if the historicApi has the pool assets pallet. If not * it will throw a BadRequest error. * * @param historicApi Decorated historic api */ checkPoolAssetsError(historicApi) { if (!historicApi.query.poolAssets) { throw new http_errors_1.BadRequest(`The runtime does not include the pool assets pallet at this block.`); } } } exports.AccountsPoolAssetsService = AccountsPoolAssetsService; //# sourceMappingURL=AccountsPoolAssetsService.js.map