@polkadot/api#ApiRx TypeScript Examples

The following examples show how to use @polkadot/api#ApiRx. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: LaminarGuardian.ts    From guardian with Apache License 2.0 6 votes vote down vote up
async setup(config: LaminarGuardianConfig) {
    const { network } = config;
    this._metadata = { ...this._metadata, network };

    const ws = new WsProvider(config.nodeEndpoint);
    const apiOptions = options({ provider: ws, types: customTypes });

    const apiRx = await firstValueFrom(ApiRx.create(apiOptions));

    // fetch token precision
    const properties = await firstValueFrom(apiRx.rpc.system.properties());
    const tokenSymbol = properties.tokenSymbol.unwrapOrDefault();
    const tokenDecimals = properties.tokenDecimals.unwrapOrDefault();
    if (tokenSymbol.length !== tokenDecimals.length) {
      throw Error(`Token symbols/decimals mismatch ${tokenSymbol} ${tokenDecimals}`);
    }
    tokenSymbol.forEach((symbol, index) => {
      this.tokenDecimals[symbol.toString()] = tokenDecimals[index].toNumber();
    });

    const getTokenPrecision = (token: string): number | undefined => {
      return this.tokenDecimals[token.toUpperCase()];
    };

    return { apiRx, getTokenPrecision, tokens: this.tokenDecimals };
  }
Example #2
Source File: BalancesTask.ts    From guardian with Apache License 2.0 6 votes vote down vote up
getBalance<CurrencyId extends Codec>(api: ApiRx, account: string, currencyId: CurrencyId): Observable<Balance> {
    return (api.derive as any).currencies.balance(account, currencyId).pipe(
      map((result: ORMLBalance) => {
        return {
          account,
          currencyId: currencyId.toString(),
          free: result.toString()
        };
      })
    );
  }
Example #3
Source File: getOraclePrice.spec.ts    From guardian with Apache License 2.0 6 votes vote down vote up
describe('getOraclePrice', () => {
  it('should get the price', async (done) => {
    const ws = new WsProvider([
      'wss://testnet-node-1.laminar-chain.laminar.one/ws',
      'wss://node-6787234140909940736.jm.onfinality.io/ws'
    ]);
    const apiRx = await firstValueFrom(ApiRx.create(options({ provider: ws })));
    const oraclePrice = getOraclePrice(apiRx);
    const FEUR = apiRx.createType('CurrencyId', 'FEUR');
    oraclePrice(FEUR).subscribe((output) => {
      console.log(output);
      expect(output).toBeTruthy();
      done();
    });
  }, 60_000);
});
Example #4
Source File: getOraclePrice.spec.ts    From guardian with Apache License 2.0 6 votes vote down vote up
describe('getOraclePrice', () => {
  let apiRx: ApiRx;

  beforeAll(async () => {
    apiRx = await firstValueFrom(ApiRx.create({ types }));
  });

  it('fetch price', () => {
    testScheduler.run(({ expectObservable }) => {
      const DOT = apiRx.createType('CurrencyId', { token: 'DOT' });

      const stream$ = getOraclePrice(apiRx)(DOT);

      expectObservable(stream$).toBe('a 999ms (b|)', {
        a: 300e18,
        b: 280e18
      });
    });
  });
});
Example #5
Source File: helpers.ts    From guardian with Apache License 2.0 6 votes vote down vote up
getOraclePrice =
  <CurrencyId extends Codec>(api: ApiRx, period: number) =>
  (tokenId: CurrencyId) => {
    // acala chain
    if (api.consts.cdpTreasury) {
      const stableCurrencyId = api.consts.cdpTreasury.getStableCurrencyId;
      const stableCurrencyIdPrice = api.consts.prices.stableCurrencyFixedPrice.toString();
      if (tokenId.eq(stableCurrencyId)) return of(Big(stableCurrencyIdPrice));
    } else {
      const ausd = api.createType('CurrencyId', 'AUSD');
      if (tokenId.eq(ausd)) return of(Big(1e18));
    }

    const price$ = observeRPC<Option<TimestampedValue>>(api.rpc.oracle.getValue, ['Aggregated', tokenId], period);

    return price$.pipe(
      filter((i) => i.isSome),
      map((i) => i.unwrap()),
      map((i) => Big(getValueFromTimestampValue(i).toString()))
    );
  }
Example #6
Source File: AcalaGuardian.ts    From guardian with Apache License 2.0 6 votes vote down vote up
async setup(config: AcalaGuardianConfig) {
    const { network } = config;
    this._metadata = { ...this._metadata, network };

    const ws = new WsProvider(config.nodeEndpoint);
    const apiOptions = options({ provider: ws, types: customTypes });

    const apiRx = await firstValueFrom(ApiRx.create(apiOptions));

    // fetch token precision
    const properties = await firstValueFrom(apiRx.rpc.system.properties());
    const tokenSymbol = properties.tokenSymbol.unwrapOrDefault();
    const tokenDecimals = properties.tokenDecimals.unwrapOrDefault();
    if (tokenSymbol.length !== tokenDecimals.length) {
      throw Error(`Token symbols/decimals mismatch ${tokenSymbol} ${tokenDecimals}`);
    }
    tokenSymbol.forEach((symbol, index) => {
      this.tokenDecimals[symbol.toString()] = tokenDecimals[index].toNumber();
    });

    const getTokenPrecision = (token: string): number | undefined => {
      return this.tokenDecimals[token.toUpperCase()];
    };

    return { apiRx, getTokenPrecision };
  }
Example #7
Source File: LiquidityPoolTask.ts    From guardian with Apache License 2.0 6 votes vote down vote up
getPoolCurrencyOptions =
  (apiRx: ApiRx, tokens: Record<string, number>) =>
  (poolId: string, currencyId: string | string[] | 'fTokens' | 'all') => {
    let currencyIds: string[] = [];
    switch (currencyId) {
      case 'all':
        currencyIds = Object.keys(tokens);
        break;
      case 'fTokens':
        currencyIds = Object.keys(tokens).filter((key) => key.startsWith('f'));
        break;
      default:
        currencyIds = typeof currencyId === 'string' ? [currencyId] : currencyId;
        break;
    }
    return of(currencyIds).pipe(
      mergeMap((x) => x),
      mergeMap((currency) =>
        combineLatest([of(currency), apiRx.query.syntheticLiquidityPools.poolCurrencyOptions(poolId, currency)])
      )
    );
  }
Example #8
Source File: TraderInfoTask.ts    From guardian with Apache License 2.0 6 votes vote down vote up
getBalances = (apiRx: ApiRx) => (account: string, poolId: number | number[] | 'all') => {
  return apiRx.query.marginProtocol.balances.entries(account).pipe(
    mergeMap((entries) =>
      entries.filter(([storageKey]) => {
        if (poolId === 'all') return true;
        const [, id] = storageKey.args;
        return castArray(poolId).includes(id.toNumber());
      })
    )
  );
}
Example #9
Source File: LiquidityPoolTask.ts    From guardian with Apache License 2.0 5 votes vote down vote up
getSyntheticPools = (apiRx: ApiRx) => (poolId: number | number[] | 'all') => {
  const upcomingPools$ = apiRx.query.baseLiquidityPoolsForSynthetic.nextPoolId().pipe(
    pairwise(),
    filter(([, next]) => !next.isZero()),
    switchMap(([prev, next]) => range(prev.toNumber(), next.toNumber())),
    distinctUntilChanged(),
    mergeMap((poolId) =>
      combineLatest([
        of(poolId.toString()),
        apiRx.query.baseLiquidityPoolsForSynthetic.pools(poolId).pipe(
          filter((x) => x.isSome),
          map((x) => x.unwrap())
        )
      ])
    )
  );

  if (poolId === 'all') {
    return apiRx.query.baseLiquidityPoolsForSynthetic.pools.entries().pipe(
      mergeMap((x) => x),
      filter(([, value]) => value.isSome),
      mergeMap(
        ([
          {
            args: [poolId]
          },
          pool
        ]) => combineLatest([of(poolId.toString()), of(pool.unwrap())])
      ),
      concatWith(upcomingPools$)
    );
  } else {
    return of(castArray(poolId)).pipe(
      mergeMap((x) => x),
      switchMap((poolId) =>
        combineLatest([of(poolId.toString()), apiRx.query.baseLiquidityPoolsForSynthetic.pools(poolId)])
      ),
      filter(([, pool]) => pool.isSome),
      mergeMap(([poolId, value]) => combineLatest([of(poolId), of(value.unwrap())]))
    );
  }
}
Example #10
Source File: StorageTask.ts    From guardian with Apache License 2.0 5 votes vote down vote up
createCall = (api: ApiRx, name: string, args: any[] = []): Observable<Output> => {
  const method = get(api.query, name);
  if (isNil(method)) throw Error(`cannot find storage ${name}`);

  return method.call(undefined, ...args).pipe(map((value) => ({ name, value })));
}
Example #11
Source File: getOraclePrice.ts    From guardian with Apache License 2.0 5 votes vote down vote up
getOraclePrice = (apiRx: ApiRx) => (tokenId: CurrencyId) => {
  if (tokenId.toString() === 'AUSD') return of(1e18);
  return apiRx.query.laminarOracle.values<Option<TimestampedValueOf>>(tokenId).pipe(
    filter((value) => value.isSome),
    map((value) => Number(value.unwrap().value.toString()))
  );
}
Example #12
Source File: TraderInfoTask.ts    From guardian with Apache License 2.0 5 votes vote down vote up
getTraderState = (apiRx: ApiRx, account: AccountId, poolId: LiquidityPoolId, period: number) => {
  const liquidityPoolId = apiRx.createType('LiquidityPoolId', poolId);
  return timer(0, period).pipe(
    switchMap(() => apiRx.rpc.margin.traderState(account, liquidityPoolId)),
    distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
    share()
  );
}
Example #13
Source File: PoolInfoTask.ts    From guardian with Apache License 2.0 5 votes vote down vote up
getPoolState = (apiRx: ApiRx, poolId: LiquidityPoolId, period: number) => {
  const stream$ = timer(0, period).pipe(
    switchMap(() => apiRx.rpc.margin.poolState(poolId)),
    distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
    shareReplay({ refCount: true, bufferSize: 1 })
  );
  return stream$;
}
Example #14
Source File: PoolInfoTask.ts    From guardian with Apache License 2.0 5 votes vote down vote up
setup = async (apiRx: ApiRx, tokens: string[]) => {
  const getPools = (poolId: number | number[] | 'all') => {
    return apiRx.query.baseLiquidityPoolsForMargin.pools.entries().pipe(
      mergeMap((entries) => {
        return entries.filter(([storageKey]) => {
          if (poolId === 'all') return true;
          const [id] = storageKey.args;
          return castArray(poolId).includes(id.toNumber());
        });
      })
    );
  };

  const getTradingPairOptions = (poolId: LiquidityPoolId, getPairId: Function): Observable<TraderPairOptions[]> => {
    return apiRx.query.marginLiquidityPools.poolTradingPairOptions.entries(poolId).pipe(
      mergeMap((x) => x),
      map(([storageKey, options]) => {
        const [, tradingPair] = storageKey.args;
        return apiRx.query.marginLiquidityPools.tradingPairOptions(tradingPair).pipe(
          map((tradingPairOptions) => {
            const maxSpread = tradingPairOptions.maxSpread;
            let askSpread = options.askSpread.unwrapOrDefault();
            let bidSpread = options.bidSpread.unwrapOrDefault();

            if (maxSpread.isSome) {
              askSpread = apiRx.createType('FixedU128', BN.max(maxSpread.unwrap(), askSpread));
              bidSpread = apiRx.createType('FixedU128', BN.max(maxSpread.unwrap(), bidSpread));
            }

            return {
              pair: {
                base: tradingPair.base.toString(),
                quote: tradingPair.quote.toString()
              },
              pairId: getPairId(tradingPair),
              enabledTrades: options.enabledTrades.toJSON(),
              askSpread: askSpread.toString(),
              bidSpread: bidSpread.toString()
            };
          })
        );
      }),
      combineLatestAll()
    );
  };

  const getPairId = (pair: { base: string; quote: string }): string => {
    const baseToken = tokens.find((x) => pair.base === x);
    const quoteToken = tokens.find((x) => pair.quote === x);
    return `${baseToken || pair.base}${quoteToken || pair.quote}`;
  };

  return { getPools, getTradingPairOptions, getPairId };
}
Example #15
Source File: getOraclePrice.ts    From guardian with Apache License 2.0 5 votes vote down vote up
getOraclePrice = (apiRx: ApiRx) => (tokenId: CurrencyId) => {
  const stableCoin = apiRx.consts.prices.getStableCurrencyId;
  if (tokenId.eq(stableCoin)) return of(Number(apiRx.consts.prices.stableCurrencyFixedPrice.toString()));
  return apiRx.query.acalaOracle.values<Option<TimestampedValueOf>>(tokenId).pipe(
    filter((value) => value.isSome),
    map((value) => Number(value.unwrap().value.toString()))
  );
}
Example #16
Source File: GuardianRegistry.spec.ts    From guardian with Apache License 2.0 5 votes vote down vote up
async setup(config: BaseSubstrateGuardianConfig) {
    const ws = new WsProvider(config.nodeEndpoint);
    const apiRx = await firstValueFrom(ApiRx.create({ provider: ws }));
    return { apiRx };
  }
Example #17
Source File: SubstrateGuardian.ts    From guardian with Apache License 2.0 5 votes vote down vote up
async setup(config: SubstrateGuardianConfig) {
    const provider = new WsProvider(config.nodeEndpoint);
    const apiRx = await firstValueFrom(ApiRx.create({ provider, types: customTypes }));
    return { apiRx };
  }
Example #18
Source File: LaminarGuardian.ts    From guardian with Apache License 2.0 5 votes vote down vote up
export default class LaminarGuardian extends BaseSubstrateGuardian<
  LaminarGuardianConfig,
  { apiRx: ApiRx; getTokenPrecision: (token: string) => number | undefined; tokens: Record<string, number> }
> {
  private readonly tokenDecimals: Record<string, number> = {};

  tasks() {
    return {
      ...super.tasks(),
      'margin.positionsByTraders': PositionsByTraderTask,
      'margin.traderInfo': TraderInfoTask,
      'margin.poolInfo': PoolInfoTask,
      'account.balances': BalancesTask,
      'oracle.prices': PricesTask,
      'synthetic.liquidityPool': LiquidityPoolTask
    };
  }

  async setup(config: LaminarGuardianConfig) {
    const { network } = config;
    this._metadata = { ...this._metadata, network };

    const ws = new WsProvider(config.nodeEndpoint);
    const apiOptions = options({ provider: ws, types: customTypes });

    const apiRx = await firstValueFrom(ApiRx.create(apiOptions));

    // fetch token precision
    const properties = await firstValueFrom(apiRx.rpc.system.properties());
    const tokenSymbol = properties.tokenSymbol.unwrapOrDefault();
    const tokenDecimals = properties.tokenDecimals.unwrapOrDefault();
    if (tokenSymbol.length !== tokenDecimals.length) {
      throw Error(`Token symbols/decimals mismatch ${tokenSymbol} ${tokenDecimals}`);
    }
    tokenSymbol.forEach((symbol, index) => {
      this.tokenDecimals[symbol.toString()] = tokenDecimals[index].toNumber();
    });

    const getTokenPrecision = (token: string): number | undefined => {
      return this.tokenDecimals[token.toUpperCase()];
    };

    return { apiRx, getTokenPrecision, tokens: this.tokenDecimals };
  }

  validationSchema() {
    return Joi.object({
      chain: Joi.valid('laminar'),
      network: Joi.valid(...laminarNetwork).required(),
      nodeEndpoint: Joi.alt(Joi.string(), Joi.array().min(1).items(Joi.string())).default(defaultNodeEndpoint)
    }).required();
  }
}
Example #19
Source File: AcalaGuardian.ts    From guardian with Apache License 2.0 5 votes vote down vote up
export default class AcalaGuardian extends BaseSubstrateGuardian<
  AcalaGuardianConfig,
  { apiRx: ApiRx; getTokenPrecision: (token: string) => number | undefined }
> {
  private readonly tokenDecimals: Record<string, number> = {};

  tasks() {
    return {
      ...super.tasks(),
      'account.balances': BalancesTask,
      'oracle.prices': PricesTask,
      'honzon.loans': LoansTask,
      'honzon.collateralAuctions': CollateralAuctionsTask,
      'dex.pools': PoolsTask
    };
  }

  async setup(config: AcalaGuardianConfig) {
    const { network } = config;
    this._metadata = { ...this._metadata, network };

    const ws = new WsProvider(config.nodeEndpoint);
    const apiOptions = options({ provider: ws, types: customTypes });

    const apiRx = await firstValueFrom(ApiRx.create(apiOptions));

    // fetch token precision
    const properties = await firstValueFrom(apiRx.rpc.system.properties());
    const tokenSymbol = properties.tokenSymbol.unwrapOrDefault();
    const tokenDecimals = properties.tokenDecimals.unwrapOrDefault();
    if (tokenSymbol.length !== tokenDecimals.length) {
      throw Error(`Token symbols/decimals mismatch ${tokenSymbol} ${tokenDecimals}`);
    }
    tokenSymbol.forEach((symbol, index) => {
      this.tokenDecimals[symbol.toString()] = tokenDecimals[index].toNumber();
    });

    const getTokenPrecision = (token: string): number | undefined => {
      return this.tokenDecimals[token.toUpperCase()];
    };

    return { apiRx, getTokenPrecision };
  }

  validationSchema() {
    return Joi.object({
      chain: Joi.valid('acala'),
      network: Joi.valid(...acalaNetwork).required(),
      nodeEndpoint: Joi.alt(Joi.string(), Joi.array().min(1).items(Joi.string())).default(defaultNodeEndpoint)
    }).required();
  }
}