UNPKG

@test-org122/hypernet-core

Version:

Hypernet Core. Represents the SDK for running the Hypernet Protocol.

254 lines (246 loc) 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AccountsRepository = void 0; const objects_1 = require("@interfaces/objects"); const ethers_1 = require("ethers"); const neverthrow_1 = require("neverthrow"); const utils_1 = require("@test-org122/utils"); class AssetInfo { constructor(assetId, name, symbol, decimals) { this.assetId = assetId; this.name = name; this.symbol = symbol; this.decimals = decimals; } } /** * Contains methods for getting Ethereum accounts, public identifiers, * balances for accounts, and depositing & withdrawing assets. */ class AccountsRepository { constructor(blockchainProvider, vectorUtils, browserNodeProvider, logUtils, blockchainUtils) { this.blockchainProvider = blockchainProvider; this.vectorUtils = vectorUtils; this.browserNodeProvider = browserNodeProvider; this.logUtils = logUtils; this.blockchainUtils = blockchainUtils; // We will cache the info about each asset type, so we only have to look it up once. this.assetInfo = new Map(); // Add a default entry for Ethereum, it's not an ERC20, it's special and it's also universal. this.assetInfo.set(ethers_1.constants.AddressZero, new AssetInfo(ethers_1.constants.AddressZero, "Ethereum", "ETH", 18)); } /** * Get the current public identifier for this instance. */ getPublicIdentifier() { return this.browserNodeProvider.getBrowserNode().map((browserNode) => { return browserNode.publicIdentifier; }); } /** * Get the Ethereum accounts associated with this instance. */ getAccounts() { return this.blockchainProvider.getProvider().andThen((provider) => { return objects_1.ResultAsync.fromPromise(provider.listAccounts(), (e) => { return e; }); }); } /** * Get all balances associated with this instance. */ getBalances() { return this.vectorUtils.getRouterChannelAddress().andThen((channelAddress) => { return this.browserNodeProvider .getBrowserNode() .andThen((browserNode) => { return browserNode.getStateChannel(channelAddress); }) .andThen((channelState) => { const assetBalanceResults = new Array(); if (channelState == null) { return neverthrow_1.combine(assetBalanceResults); } for (let i = 0; i < channelState.assetIds.length; i++) { const assetBalanceResult = this._getAssetBalance(i, channelState); assetBalanceResults.push(assetBalanceResult); } return neverthrow_1.combine(assetBalanceResults); }) .map((assetBalances) => { return new objects_1.Balances(assetBalances); }); }); } /** * Get balance for a particular asset for this instance * @param assetAddress the (Ethereum) address of the token to get the balance of */ getBalanceByAsset(assetAddress) { return this.getBalances().andThen((balances) => { for (const assetBalance of balances.assets) { if (assetBalance.assetAddresss === assetAddress) { // The user has a balance of the selected asset type, so we have an asset balance // to give back. return neverthrow_1.okAsync(assetBalance); } } // The user does not have a balance in the existing asset. The only problem here // is that we still would like to return a proper name for the asset. return this._getAssetInfo(assetAddress).map((assetInfo) => { return new objects_1.AssetBalance(assetAddress, assetInfo.name, assetInfo.symbol, assetInfo.decimals, objects_1.BigNumber.from(0), objects_1.BigNumber.from(0), objects_1.BigNumber.from(0)); }); }); } /** * Deposit funds into this instance of Hypernet Core * @param assetAddress the (Ethereum) token address to deposit * @param amount the amount of the token to deposit */ depositFunds(assetAddress, amount) { let signer; let channelAddress; let browserNode; return utils_1.ResultUtils.combine([ this.blockchainProvider.getSigner(), this.vectorUtils.getRouterChannelAddress(), this.browserNodeProvider.getBrowserNode(), ]) .andThen((vals) => { [signer, channelAddress, browserNode] = vals; let tx; if (assetAddress === "0x0000000000000000000000000000000000000000") { this.logUtils.log("Transferring ETH."); // send eth tx = objects_1.ResultAsync.fromPromise(signer.sendTransaction({ to: channelAddress, value: amount }), (err) => { return err; }); } else { this.logUtils.log("Transferring an ERC20 asset."); // send an actual erc20 token return this.blockchainUtils.erc20Transfer(assetAddress, channelAddress, amount); } return tx; }) .andThen((tx) => { // TODO: Wait on this, break it up, this could take a while return objects_1.ResultAsync.fromPromise(tx.wait(), (e) => e); }) .andThen(() => { if (browserNode == null || channelAddress == null) { return neverthrow_1.errAsync(new Error("Really screwed up!")); } return browserNode.reconcileDeposit(assetAddress, channelAddress); }) .andThen((depositRes) => { // I can not for the life of me figure out why depositRes is coming back // as "unknown" const depositChannelAddress = depositRes; // Sanity check, the deposit was for the channel we tried to deposit into. if (depositChannelAddress !== channelAddress) { return neverthrow_1.errAsync(new Error("Something has gone horribly wrong!")); } return neverthrow_1.okAsync(null); }); } /** * Withdraw funds from this instance of Hypernet Core to a specified (Ethereum) destination * @param assetAddress the token address to withdraw * @param amount the amount of the token to withdraw * @param destinationAddress the destination (Ethereum) address to withdraw to */ withdrawFunds(assetAddress, amount, destinationAddress) { const prerequisites = utils_1.ResultUtils.combine([ this.browserNodeProvider.getBrowserNode(), this.vectorUtils.getRouterChannelAddress(), ]); return prerequisites .andThen((vals) => { const [browserNode, channelAddress] = vals; return browserNode.withdraw(channelAddress, amount.toString(), assetAddress, destinationAddress, "0"); }) .map(() => { return; }); } /** * Mint the test token to the provided address * @param amount the amount of the test token to mint * @param to the (Ethereum) address to mint the test token to */ mintTestToken(amount, to) { const resp = this.blockchainUtils.mintToken(amount, to); return resp .andThen((mintTx) => { return objects_1.ResultAsync.fromPromise(mintTx.wait(), (e) => { return e; }); }) .map(() => { return; }); } _getAssetBalance(i, channelState) { const assetAddress = channelState.assetIds[i]; return this._getAssetInfo(assetAddress).map((assetInfo) => { const amount = objects_1.BigNumber.from(channelState.balances[i].amount[1]); // Return the asset balance const assetBalance = new objects_1.AssetBalance(assetAddress, assetInfo.name, assetInfo.symbol, assetInfo.decimals, amount, objects_1.BigNumber.from(0), // @todo figure out how to grab the locked amount amount); return assetBalance; }); } // TODO: fix it, tokenContract.name() not working _getAssetInfo(assetAddress) { /* let name: string; let symbol: string; let tokenContract: Contract; // First, check if we have already cached the info about this asset. const cachedAssetInfo = this.assetInfo.get(assetAddress); if (cachedAssetInfo == null) { // No cached info, we'll have to get it return this.blockchainProvider .getSigner() .andThen((signer) => { tokenContract = new Contract(assetAddress, this.erc20Abi, signer); return ResultAsync.fromPromise<string | null, BlockchainUnavailableError>(tokenContract.name(), (err) => { return err as BlockchainUnavailableError; }); }) .andThen((myName) => { if (myName == null || myName == "") { name = `Unknown Token (${assetAddress})`; } else { name = myName; } return ResultAsync.fromPromise<string | null, BlockchainUnavailableError>(tokenContract.symbol(), (err) => { return err as BlockchainUnavailableError; }); }) .andThen((mySymbol) => { if (mySymbol == null || mySymbol == "") { symbol = "Unk"; } else { symbol = mySymbol; } return ResultAsync.fromPromise<number | null, BlockchainUnavailableError>(tokenContract.decimals(), (err) => { return err as BlockchainUnavailableError; }); }) .map((myDecimals) => { const decimals = myDecimals ?? 0; const assetInfo = new AssetInfo(assetAddress, name, symbol, decimals); // Store the cached info this.assetInfo.set(assetAddress, assetInfo); return assetInfo; }); } // We have cached info return okAsync(cachedAssetInfo);*/ return neverthrow_1.okAsync(new AssetInfo(assetAddress, "", "", 0)); } } exports.AccountsRepository = AccountsRepository; //# sourceMappingURL=AccountsRepository.js.map