UNPKG

edge-core-js

Version:

Edge account & wallet management library

1,880 lines (1,559 loc) 57.4 kB
// @flow import type { Disklet } from "disklet"; import type { FetchHeaders, FetchOptions, FetchResponse } from "serverlet"; import type { Subscriber } from "yaob"; export * from "./error"; export * from "./fake-types"; export * from "./server-cleaners"; export * from "./server-types"; // --------------------------------------------------------------------- // helper types // --------------------------------------------------------------------- /** A JSON object (as opposed to an array or primitive). */ export type JsonObject = { [name: string]: any; // TODO: this needs to become `mixed` } /** When we return errors explicitly instead of throwing them */ export type EdgeResult<T> = | { ok: true; result: T } | { ok: false; error: mixed }; /** A collection of mixed extra methods exposed by a plugin. */ export type EdgeOtherMethods = { +[name: string]: any; } /** We frequently index things by pluginId, so provide a helper. */ export type EdgePluginMap<Value> = { [pluginId: string]: Value; } // --------------------------------------------------------------------- // io types // --------------------------------------------------------------------- // Node.js randomBytes function: export type EdgeRandomFunction = (bytes: number) => Uint8Array; // The scrypt function Edge expects: export type EdgeScryptFunction = ( data: Uint8Array, salt: Uint8Array, n: number, r: number, p: number, dklen: number, ) => Promise<Uint8Array>; // The subset of the fetch function Edge expects: export type EdgeFetchOptions = FetchOptions & { corsBypass?: "auto" | "always" | "never"; }; export type EdgeFetchHeaders = FetchHeaders; export type EdgeFetchResponse = FetchResponse; export type EdgeFetchFunction = ( uri: string, opts?: EdgeFetchOptions, ) => Promise<EdgeFetchResponse>; /** * Access to platform-specific resources. * The core never talks to the outside world on its own, * but always goes through this object. */ export type EdgeIo = { // Crypto: +random: EdgeRandomFunction; +scrypt: EdgeScryptFunction; // Local io: +disklet: Disklet; +fetch: EdgeFetchFunction; /** * This is like `fetch`, but will try to avoid CORS limitations * on platforms where that may be a problem. * * @deprecated Use EdgeIo.fetch instead, which now includes CORS avoidance by default */ +fetchCors: EdgeFetchFunction; } // logging ------------------------------------------------------------- export type EdgeLogMethod = (...args: any[]) => void; /** * Logs a message. * * Call `log(message)` for normal information messages, * or `log.warn(message)` / `log.error(message)` for something more severe. * To record crash information, use `log.crash(error, json)` for errors, * and `log.breadcrumb(message, json)` for data leading up to crashes. */ export type EdgeLog = EdgeLogMethod & { // Crash logging: +breadcrumb: (message: string, metadata: JsonObject) => void; +crash: (error: mixed, metadata: JsonObject) => void; // Message logging: +warn: EdgeLogMethod; +error: EdgeLogMethod; }; export type EdgeLogType = "info" | "warn" | "error"; export type EdgeLogSettings = { sources: { [pluginId: string]: EdgeLogType | "silent" }; defaultLogLevel: EdgeLogType | "silent"; } /** * The EdgeLog function stringifies its arguments and adds * some extra information to form this event type. */ export type EdgeLogEvent = { message: string; source: string; time: Date; type: EdgeLogType; } export type EdgeBreadcrumbEvent = { message: string; metadata: JsonObject; source: string; time: Date; } export type EdgeCrashEvent = { error: mixed; metadata: JsonObject; source: string; time: Date; } /** * Receives crash reports. * The app should implement this interface and pass it to the context. */ export type EdgeCrashReporter = { +logBreadcrumb: (breadcrumb: EdgeBreadcrumbEvent) => void; +logCrash: (crash: EdgeCrashEvent) => void; } /** * Receives log messages. * The app should implement this function and pass it to the context. */ export type EdgeOnLog = (event: EdgeLogEvent) => void; // plugins ------------------------------------------------------------- /** * On React Native, each plugin can provide a bridge to whatever native * io it needs. */ export type EdgeNativeIo = { [packageName: string]: EdgeOtherMethods; } /** * All core plugins receive these options at creation time. */ export type EdgeCorePluginOptions = { /** Load-time options (like API keys) passed into the context */ initOptions: JsonObject; /** Data provided by the info server */ infoPayload: JsonObject; // Access to the world outside the plugin: io: EdgeIo; log: EdgeLog; // Plugin-scoped logging nativeIo: EdgeNativeIo; // Only filled in on React Native pluginDisklet: Disklet; // Plugin-scoped local storage } // --------------------------------------------------------------------- // key types // --------------------------------------------------------------------- export type EdgeWalletInfo = { id: string; type: string; keys: JsonObject; } export type EdgeWalletInfoFull = EdgeWalletInfo & { appIds: string[]; archived: boolean; created?: Date; deleted: boolean; hidden: boolean; imported?: boolean; migratedFromWalletId?: string; sortIndex: number; }; export type EdgeWalletState = { archived?: boolean; deleted?: boolean; hidden?: boolean; migratedFromWalletId?: string; sortIndex?: number; } export type EdgeWalletStates = { [walletId: string]: EdgeWalletState; } // --------------------------------------------------------------------- // currency types // --------------------------------------------------------------------- /** * Different currencies support different types of on-chain memos, * so this structure describes the options that are available, * along with the applicable limits. */ export type EdgeMemoOption = | { type: "text"; hidden?: boolean; memoName?: string; /** Maximum number of text characters */ maxLength?: number; } | { type: "number"; hidden?: boolean; memoName?: string; /** * Maximum numerical value. * Numbers are passed as decimal strings. */ maxValue?: string; } | { type: "hex"; hidden?: boolean; memoName?: string; /** Number of hexadecimal bytes. */ maxBytes?: number; minBytes?: number; }; export type EdgeMemo = { type: "text" | "number" | "hex"; value: string; /** Should we hide this from the user, such as for OP_RETURN? */ hidden?: boolean; /** What does the chain call this? Defaults to "memo". */ memoName?: string; } export type EdgeAssetAmount = { pluginId: string; tokenId: EdgeTokenId; nativeAmount?: string; } export type EdgeFiatAmount = { // core-js style fiat code including 'iso:' fiatCurrencyCode: string; fiatAmount: string; } export type EdgeTxActionSwap = { actionType: "swap"; swapInfo: EdgeSwapInfo; orderId?: string; orderUri?: string; isEstimate?: boolean; canBePartial?: boolean; fromAsset: EdgeAssetAmount; toAsset: EdgeAssetAmount; payoutAddress: string; payoutWalletId: string; refundAddress?: string; } export type EdgeTxActionStake = { actionType: "stake"; pluginId: string; stakeAssets: EdgeAssetAmount[]; } export type EdgeTxActionFiat = { actionType: "fiat"; orderId: string; orderUri?: string; isEstimate: boolean; fiatPlugin: { providerId: string; providerDisplayName: string; supportEmail?: string; }; payinAddress?: string; payoutAddress?: string; fiatAsset: EdgeFiatAmount; cryptoAsset: EdgeAssetAmount; } export type EdgeTxActionTokenApproval = { actionType: "tokenApproval"; tokenApproved: EdgeAssetAmount; tokenContractAddress: string; contractAddress: string; } export type EdgeTxAction = | EdgeTxActionSwap | EdgeTxActionStake | EdgeTxActionFiat | EdgeTxActionTokenApproval; export type EdgeTxAmount = { tokenId: EdgeTokenId; nativeAmount: string; } export type EdgeAssetActionType = | "claim" | "claimOrder" | "stake" | "stakeNetworkFee" | "stakeOrder" | "unstake" | "unstakeNetworkFee" | "unstakeOrder" | "swap" | "swapNetworkFee" | "swapOrderPost" | "swapOrderFill" | "swapOrderCancel" | "buy" | "sell" | "sellNetworkFee" | "tokenApproval" | "transfer" | "transferNetworkFee"; export type EdgeAssetAction = { assetActionType: EdgeAssetActionType; } // token info ---------------------------------------------------------- export type EdgeDenomination = { // Multiply a display amount by this number to get the native amount. // BTC would use "100000000", for instance: multiplier: string; // A display name for this denomination, like "BTC", "bits", or "sats": name: string; // A prefix to add to the formatted number, like "₿", "ƀ", or "s": symbol?: string; } /** * Information used to display a token or currency to the user. */ export type EdgeToken = { // The short code used on exchanges, such as "BTC": currencyCode: string; // How many decimal places to shift the native amount. // The first item in this array is always the default for exchanges: denominations: EdgeDenomination[]; // The full marketing name, such as "Bitcoin": displayName: string; // Each currency plugin decides what this contains, // such as a contract address. // This may be `undefined` for special built-in tokens // such as staking balances. networkLocation: JsonObject | void; } /** * A normal tokenId (chosen by the currency plugin), * or `null` to indicate the parent currency (such as "ETH"). */ export type EdgeTokenId = string | null; export type EdgeTokenMap = { // Each currency plugin decides how to generate this ID, // such as by using the contract address: [tokenId: string]: EdgeToken; } /** * Available tokens stored in the `EdgeCurrencyInfo`, * or parsed out of URI's. */ export type EdgeMetaToken = { currencyCode: string; currencyName: string; contractAddress?: string; denominations: EdgeDenomination[]; symbolImage?: string; } /** * Tokens passed to `addCustomToken`. */ export type EdgeTokenInfo = { currencyCode: string; currencyName: string; contractAddress: string; multiplier: string; } /** * The search parameter for {@link EdgeCurrencyConfig.getTokenDetails} and * {@link EdgeCurrencyTools.getTokenDetails}. */ export type EdgeGetTokenDetailsFilter = { /** Contract address or other unique onchain identifier. */ contractAddress?: string; /** Ticker symbol for the currency. */ currencyCode?: string; } // currency info ------------------------------------------------------- export type EdgeObjectTemplate = Array< | { // Displayed as a decimal number, but saved as an integer string. // The multiplier gives the position of the display decimal point. // This is only used for custom fees. // It is *not* supported for custom tokens: type: "nativeAmount"; key: string; displayName: string; displayMultiplier: string; } | { // An integer, saved as a JavaScript `number` type: type: "number"; key: string; displayName: string; } | { type: "string"; key: string; displayName: string; } >; export type EdgeCurrencyInfo = { // Basic currency information: +pluginId: string; /** deprecated: refers to chain, use chainDisplayName instead */ displayName: string; chainDisplayName: string; assetDisplayName: string; walletType: string; // Native token information: currencyCode: string; denominations: EdgeDenomination[]; // Chain information: canAdjustFees?: boolean; // Defaults to true canImportKeys?: boolean; // Defaults to false canReplaceByFee?: boolean; // Defaults to false customFeeTemplate?: EdgeObjectTemplate; // Indicates custom fee support customTokenTemplate?: EdgeObjectTemplate; // Indicates custom token support requiredConfirmations?: number; // Block confirmations required for a tx /** * Lists the types of memos this chain supports. * A missing or empty list means no memo support. */ memoOptions?: EdgeMemoOption[]; /** True if the transaction can have multiple memos at once: */ multipleMemos?: boolean; // Explorers: addressExplorer: string; blockExplorer?: string; transactionExplorer: string; xpubExplorer?: string; // Flags: unsafeBroadcastTx?: boolean; unsafeMakeSpend?: boolean; unsafeSyncNetwork?: boolean; usesChangeServer?: boolean; /** @deprecated The default user settings are always `{}` */ defaultSettings?: JsonObject; /** @deprecated Use EdgeCurrencyPlugin.getBuiltinTokens instead */ metaTokens?: EdgeMetaToken[]; /** @deprecated Use memoOptions instead. */ memoMaxLength?: number; // Max number of text characters, if supported /** @deprecated Use memoOptions instead. */ memoMaxValue?: string; // Max numerical value, if supported /** @deprecated Use memoOptions instead. */ memoType?: "text" | "number" | "hex" | "other"; // undefined means no memo support } // spending ------------------------------------------------------------ export type EdgeMetadata = { bizId?: number; category?: string; exchangeAmount?: { [fiatCurrencyCode: string]: number }; name?: string; notes?: string; } /** * Like EdgeMetadata, but passing `null` will delete a saved value, * while passing `undefined` will leave the value unchanged. */ export type EdgeMetadataChange = { bizId?: number | null; category?: string | null; exchangeAmount?: { [fiatCurrencyCode: string]: number | null }; name?: string | null; notes?: string | null; } export type EdgeTxSwap = { orderId?: string; orderUri?: string; isEstimate: boolean; // The EdgeSwapInfo from the swap plugin: plugin: { pluginId: string; displayName: string; supportEmail?: string; }; // Address information: payoutAddress: string; payoutCurrencyCode: string; payoutNativeAmount: string; payoutWalletId: string; refundAddress?: string; } export type EdgeConfirmationState = // More than `EdgeCurrencyInfo.requiredConfirmations`: | "confirmed" // Dropped from the network without confirmations: | "dropped" // Confirmed, but failed on-chain execution (exceeded gas limit, // smart-contract failure, etc): | "failed" // We don't know the chain height yet: | "syncing" // No confirmations yet: | "unconfirmed" // Something between 1 and `requiredConfirmations`. // Currency engines can always return a number, // and the core will translate it into one of the other states: | number; export type EdgeTransaction = { /** * The asset used to query this transaction. * The amounts and metadata will reflect the chosen asset. */ tokenId: EdgeTokenId; // Amounts: nativeAmount: string; networkFees: EdgeTxAmount[]; // Confirmation status: confirmations?: EdgeConfirmationState; blockHeight: number; date: number; // Transaction info: txid: string; signedTx: string; memos: EdgeMemo[]; ourReceiveAddresses: string[]; /** App-provided per-asset action data */ assetAction?: EdgeAssetAction; /** Plugin-provided action data for all assets in a transaction */ chainAction?: EdgeTxAction; /** Plugin-provided per-asset action data */ chainAssetAction?: EdgeAssetAction; /** App-provided action data for all assets in a transaction */ savedAction?: EdgeTxAction; /** This has the same format as the `customNetworkFee` */ feeRateUsed?: JsonObject; // Spend-specific metadata: deviceDescription?: string; networkFeeOption?: "high" | "standard" | "low" | "custom"; requestedCustomFee?: JsonObject; spendTargets?: Array<{ +currencyCode: string; // Saved for future reference +nativeAmount: string; +publicAddress: string; /** @deprecated Use `EdgeTransaction.memos` instead */ +memo: string | void; /** @deprecated Use `EdgeTransaction.memos` instead */ +uniqueIdentifier: string | void; }>; swapData?: EdgeTxSwap; txSecret?: string; // Monero decryption key /** * True if the user themselves signed & sent this transaction. * This will not be true for transactions created by other users, * smart contracts, assets becoming unstaked, or anything else automatic. * A send doesn't necessarily spend money, although it often does. */ isSend: boolean; // Core: metadata?: EdgeMetadata; walletId: string; otherParams?: JsonObject; /** @deprecated Use tokenId instead */ currencyCode: string; /** @deprecated Use networkFees instead */ networkFee: string; /** @deprecated Use networkFees instead */ parentNetworkFee?: string; } export type EdgeTransactionEvent = { isNew: boolean; transaction: EdgeTransaction; } export type EdgeSpendTarget = { nativeAmount?: string; otherParams?: JsonObject; publicAddress?: string; /** @deprecated. Use `EdgeSpendInfo.memos` instead. */ memo?: string; /** @deprecated. Use `EdgeSpendInfo.memos` instead. */ uniqueIdentifier?: string; // Use memo instead. } export type EdgePaymentProtocolInfo = { domain: string; memo: string; merchant: string; nativeAmount: string; spendTargets: EdgeSpendTarget[]; } export type EdgeSpendInfo = { // Basic information: tokenId: EdgeTokenId; privateKeys?: string[]; spendTargets: EdgeSpendTarget[]; memos?: EdgeMemo[]; // Options: noUnconfirmed?: boolean; networkFeeOption?: "high" | "standard" | "low" | "custom"; customNetworkFee?: JsonObject; // Some kind of currency-specific JSON /** Enables RBF on chains where RBF is optional */ enableRbf?: boolean; pendingTxs?: EdgeTransaction[]; /** @deprecated Use EdgeCurrencyWallet.accelerate instead */ rbfTxid?: string; skipChecks?: boolean; // Core: assetAction?: EdgeAssetAction; savedAction?: EdgeTxAction; metadata?: EdgeMetadata; swapData?: EdgeTxSwap; otherParams?: JsonObject; } // query data ---------------------------------------------------------- export type EdgeDataDump = { walletId: string; walletType: string; data: { [dataCache: string]: JsonObject; }; } /** * Addresses may appear in any order that the plugin chooses, * based on how the user should see them. If you need a specific address type, * use the `addressType` to find what you need. */ export type EdgeAddress = { addressType: string; // 'publicAddress' | 'segwitAddress' | 'legacyAddress' | 'fooAddress' publicAddress: string; nativeBalance?: string; } /** @deprecated */ export type EdgeFreshAddress = { publicAddress: string; segwitAddress?: string; legacyAddress?: string; nativeBalance?: string; segwitNativeBalance?: string; legacyNativeBalance?: string; } /** * Balances, unlock dates, and other information about staked funds. * * The currency engine is responsible for keeping this up to date. * For instance, if the user submits a transaction to unlock funds, * the engine should update this data once it detects that transaction, * and then again once the funds actually unlock some time later. * * As with wallet balances, this data may not be reliable until the * `syncRatio` hits 1. */ export type EdgeStakingStatus = { // Funds can be in various stages of being locked or unlocked, // so each row can describe a single batch of locked coins. // Adding together the rows in this array should give the // total amount of locked-up funds in the wallet: stakedAmounts: Array<{ nativeAmount: string; // Maybe these funds are not the chain's parent currency: // tokenId?: string, // Maybe these funds are being unlocked? unlockDate?: Date; // Feel free to add other weird coin states here. // We can standardize them later if they are common: otherParams?: JsonObject; }>; } export type EdgeTxidMap = { [txid: string]: number; } // URI ----------------------------------------------------------------- export type WalletConnect = { uri: string; topic: string; version?: string; bridge?: string; key?: string; } export type EdgeParsedUri = { bitIDCallbackUri?: string; bitIDDomain?: string; bitidKycProvider?: string; // Experimental bitidKycRequest?: string; // Experimental bitidPaymentAddress?: string; // Experimental bitIDURI?: string; expireDate?: Date; legacyAddress?: string; metadata?: EdgeMetadata; minNativeAmount?: string; nativeAmount?: string; paymentProtocolUrl?: string; privateKeys?: string[]; publicAddress?: string; returnUri?: string; segwitAddress?: string; token?: EdgeMetaToken; tokenId?: EdgeTokenId; uniqueIdentifier?: string; // Ripple payment id walletConnect?: WalletConnect; /** @deprecated Use tokenId instead */ currencyCode?: string; } export type EdgeEncodeUri = { publicAddress: string; nativeAmount?: string; label?: string; message?: string; currencyCode?: string; } // options ------------------------------------------------------------- export type EdgeTokenIdOptions = { tokenId: EdgeTokenId; } export type EdgeGetTransactionsOptions = { // Filtering: startDate?: Date; endDate?: Date; searchString?: string; spamThreshold?: string; tokenId: EdgeTokenId; } export type EdgeStreamTransactionOptions = { /** * The number of entries to return in each batch. * Defaults to something reasonable, like 10. */ batchSize?: number; /** * The number entries to return on the first batch. * Defaults to `batchSize`. */ firstBatchSize?: number; /** Only return transactions newer than this date */ afterDate?: Date; /** Only return transactions older than this date */ beforeDate?: Date; /** Only return transactions matching this string */ searchString?: string; /** Filter incoming transactions with a `nativeAmount` below this */ spamThreshold?: string; /** The token to query, or undefined for the main currency */ tokenId: EdgeTokenId; } export type EdgeGetReceiveAddressOptions = EdgeTokenIdOptions & { forceIndex?: number; }; export type EdgeEngineActivationOptions = { // If null, activate parent wallet: activateTokenIds: EdgeTokenId[]; // Wallet if the user is paying with a different currency: paymentInfo?: { wallet: EdgeCurrencyWallet; tokenId: EdgeTokenId; }; } export type EdgeEngineGetActivationAssetsOptions = { // All wallets in the users account. This allows the engine to choose // which wallets can fulfill this activation request currencyWallets: { [walletId: string]: EdgeCurrencyWallet }; // If null, activate parent wallet: activateTokenIds: EdgeTokenId[]; } export type EdgeEnginePrivateKeyOptions = { privateKeys?: JsonObject; } export type EdgeEngineSyncNetworkOptions = { subscribeParam?: { address: string; /** * The checkpoint from the change-server. Mempool transactions are an * example of updates without checkpoints. * */ checkpoint?: string; }; privateKeys?: JsonObject; } export type EdgeSaveTxActionOptions = { txid: string; tokenId: EdgeTokenId; assetAction: EdgeAssetAction; savedAction: EdgeTxAction; } export type EdgeSaveTxMetadataOptions = { txid: string; tokenId: EdgeTokenId; metadata: EdgeMetadataChange; } export type EdgeSignMessageOptions = { otherParams?: JsonObject; } // engine -------------------------------------------------------------- export type EdgeCurrencyEngineCallbacks = { +onAddressChanged: () => void; +onAddressesChecked: (progressRatio: number) => void; +onNewTokens: (tokenIds: string[]) => void; +onSeenTxCheckpoint: (checkpoint: string) => void; +onStakingStatusChanged: (status: EdgeStakingStatus) => void; +onSubscribeAddresses: ( paramsOrAddresses: | Array<{ address: string; checkpoint?: string }> /** @deprecated Use the array of param objects instead. */ | string[], ) => void; +onTokenBalanceChanged: ( tokenId: EdgeTokenId, balance: string, ) => void; +onTransactions: (transactionEvents: EdgeTransactionEvent[]) => void; +onTxidsChanged: (txids: EdgeTxidMap) => void; +onUnactivatedTokenIdsChanged: ( unactivatedTokenIds: string[], ) => void; +onWcNewContractCall: (payload: JsonObject) => void; /** @deprecated onTransactionsChanged handles confirmation changes */ +onBlockHeightChanged: (blockHeight: number) => void; /** @deprecated Use onTokenBalanceChanged instead */ +onBalanceChanged: ( currencyCode: string, nativeBalance: string, ) => void; /** @deprecated Use onTransactions */ +onTransactionsChanged: (transactions: EdgeTransaction[]) => void; } export type EdgeCurrencyEngineOptions = { callbacks: EdgeCurrencyEngineCallbacks; // Engine state kept by the core: seenTxCheckpoint?: string; /** True if we only need a balance and the ability to spend it. */ lightMode?: boolean; // Wallet-scoped IO objects: log: EdgeLog; walletLocalDisklet: Disklet; walletLocalEncryptedDisklet: Disklet; // User settings: customTokens: EdgeTokenMap; enabledTokenIds: string[]; userSettings: JsonObject | void; } export type EdgeCurrencyEngine = { +changeUserSettings: (settings: JsonObject) => Promise<void>; /** * Starts any persistent resources the engine needs, such as WebSockets. * Engines should use `syncNetwork` for periodic tasks (polling), * rather than trying to manage those by itself. */ +startEngine: () => Promise<void>; /** * Shut down the engine, including open sockets, timers, * and any in-progress tasks that support cancellation. */ +killEngine: () => Promise<void>; /** * Polls the blockchain for updates. * The return value is the delay (in ms) that the engine wants to wait * before its next poll. For engines with active address subscriptions, * the core will ignore this number and simply wait for the next * on-chain update. * Engines with `EdgeCurrencyInfo.unsafeSyncNetwork` * will receive their private keys in the arguments. */ +syncNetwork?: ( opts: EdgeEngineSyncNetworkOptions, ) => Promise<number>; // Engine status: +resyncBlockchain: () => Promise<void>; +dumpData: () => Promise<EdgeDataDump>; // Chain state: +getBlockHeight: () => number; +getBalance: (opts: EdgeTokenIdOptions) => string; +getNumTransactions: (opts: EdgeTokenIdOptions) => number; +getTransactions: ( opts: EdgeTokenIdOptions, ) => Promise<EdgeTransaction[]>; +getTxids?: () => EdgeTxidMap; // Tokens: +changeCustomTokens?: (tokens: EdgeTokenMap) => Promise<void>; +changeEnabledTokenIds?: (tokenIds: string[]) => Promise<void>; // Asset activation: +engineGetActivationAssets?: ( options: EdgeEngineGetActivationAssetsOptions, ) => Promise<EdgeGetActivationAssetsResults>; +engineActivateWallet?: ( options: EdgeEngineActivationOptions, ) => Promise<EdgeActivationQuote>; // Addresses: +getAddresses?: ( opts: EdgeGetReceiveAddressOptions, ) => Promise<EdgeAddress[]>; /** @deprecated */ +getFreshAddress: ( opts: EdgeGetReceiveAddressOptions, ) => Promise<EdgeFreshAddress>; +addGapLimitAddresses: (addresses: string[]) => Promise<void>; +isAddressUsed: (address: string) => Promise<boolean>; // Spending: +getMaxSpendable?: ( spendInfo: EdgeSpendInfo, opts?: EdgeEnginePrivateKeyOptions, ) => Promise<string>; +makeSpend: ( spendInfo: EdgeSpendInfo, opts?: EdgeEnginePrivateKeyOptions, ) => Promise<EdgeTransaction>; +signTx: ( transaction: EdgeTransaction, privateKeys: JsonObject, ) => Promise<EdgeTransaction>; +broadcastTx: ( transaction: EdgeTransaction, opts?: EdgeEnginePrivateKeyOptions, ) => Promise<EdgeTransaction>; +saveTx: (transaction: EdgeTransaction) => Promise<void>; +sweepPrivateKeys?: ( spendInfo: EdgeSpendInfo, ) => Promise<EdgeTransaction>; +getPaymentProtocolInfo?: ( paymentProtocolUrl: string, ) => Promise<EdgePaymentProtocolInfo>; // Signing: +signBytes?: ( bytes: Uint8Array, privateKeys: JsonObject, opts: EdgeSignMessageOptions, ) => Promise<string>; // Accelerating: +accelerate?: ( tx: EdgeTransaction, ) => Promise<EdgeTransaction | null>; // Staking: +getStakingStatus?: () => Promise<EdgeStakingStatus>; // Escape hatch: +otherMethods?: EdgeOtherMethods; +otherMethodsWithKeys?: EdgeOtherMethods; /** @deprecated Replaced by changeEnabledTokenIds */ +enableTokens?: (tokens: string[]) => Promise<void>; /** @deprecated Replaced by changeEnabledTokenIds */ +disableTokens?: (tokens: string[]) => Promise<void>; /** @deprecated Replaced by changeCustomTokens */ +addCustomToken?: (token: EdgeTokenInfo & EdgeToken) => Promise<void>; /** @deprecated Provide EdgeCurrencyTools.getDisplayPrivateKey: */ +getDisplayPrivateSeed?: (privateKeys: JsonObject) => string | null; /** @deprecated Provide EdgeCurrencyTools.getDisplayPublicKey: */ +getDisplayPublicSeed?: () => string | null; /** * @deprecated Replaced by `signBytes`. * Various plugins implement this function with inconsistent encodings. */ +signMessage?: ( message: string, privateKeys: JsonObject, opts: EdgeSignMessageOptions, ) => Promise<string>; } // currency plugin ----------------------------------------------------- export type EdgeCurrencyTools = { // Keys: +checkPublicKey?: (publicKey: JsonObject) => Promise<boolean>; +createPrivateKey: ( walletType: string, opts?: JsonObject, ) => Promise<JsonObject>; +derivePublicKey: ( privateWalletInfo: EdgeWalletInfo, ) => Promise<JsonObject>; +getDisplayPrivateKey?: ( privateWalletInfo: EdgeWalletInfo, ) => Promise<string>; +getDisplayPublicKey?: ( publicWalletInfo: EdgeWalletInfo, ) => Promise<string>; +getDisplayPublicKeys?: (publicWalletInfo: EdgeWalletInfo) => { [key: string]: string; }; +getSplittableTypes?: ( publicWalletInfo: EdgeWalletInfo, ) => string[] | Promise<string[]>; +importPrivateKey?: ( key: string, opts?: JsonObject, ) => Promise<JsonObject>; +getTokenDetails?: ( filter: EdgeGetTokenDetailsFilter, ) => Promise<EdgeToken[]>; // Derives a tokenId string from a token's network information: +getTokenId?: (token: EdgeToken) => Promise<string>; // URIs: +parseUri: ( uri: string, currencyCode?: string, customTokens?: EdgeMetaToken[], ) => Promise<EdgeParsedUri>; +encodeUri: ( obj: EdgeEncodeUri, customTokens?: EdgeMetaToken[], ) => Promise<string>; } export type EdgeCurrencyPlugin = { +currencyInfo: EdgeCurrencyInfo; +getBuiltinTokens?: () => Promise<EdgeTokenMap>; +makeCurrencyTools: () => Promise<EdgeCurrencyTools>; +makeCurrencyEngine: ( walletInfo: EdgeWalletInfo, opts: EdgeCurrencyEngineOptions, ) => Promise<EdgeCurrencyEngine>; +updateInfoPayload?: (infoPayload: JsonObject) => Promise<void>; // Escape hatch: +otherMethods?: EdgeOtherMethods; } // wallet -------------------------------------------------------------- export type EdgeBalances = { [currencyCode: string]: string; } export type EdgeBalanceMap = Map<EdgeTokenId, string>; export type EdgeReceiveAddress = EdgeFreshAddress & { metadata: EdgeMetadata; nativeAmount: string; }; export type EdgeCurrencyWalletEvents = { addressChanged: void; close: void; enabledDetectedTokens: string[]; newTransactions: EdgeTransaction[]; transactionsChanged: EdgeTransaction[]; /** * Something has removed transactions, * so the GUI should refresh the transaction list. * * We may pass dropped txid's as `string[]` in the future. * A missing array means "check everything", such with resync. */ transactionsRemoved: void; wcNewContractCall: JsonObject; } export type EdgeGetActivationAssetsOptions = { activateWalletId: string; // If null, activate parent wallet: activateTokenIds: EdgeTokenId[]; } export type EdgeGetActivationAssetsResults = { assetOptions: Array<{ paymentWalletId?: string; // If walletId is present, use MUST activate with this wallet currencyPluginId: string; tokenId: EdgeTokenId; }>; } export type EdgeActivationOptions = { activateWalletId: string; // If null, activate parent wallet: activateTokenIds: EdgeTokenId[]; // Wallet if the user is paying with a different currency: paymentInfo?: { walletId: string; tokenId: EdgeTokenId; }; } export type EdgeActivationApproveOptions = { metadata?: EdgeMetadata; } export type EdgeActivationResult = { +transactions: EdgeTransaction[]; } export type EdgeActivationQuote = { +paymentWalletId: string; +paymentTokenId: EdgeTokenId; +fromNativeAmount: string; +networkFee: EdgeTxAmount & { /** @deprecated use contextual APIs to get the currency's pluginId */ +currencyPluginId: string; }; +approve: ( opts?: EdgeActivationApproveOptions, ) => Promise<EdgeActivationResult>; close: () => Promise<void>; } export type EdgeCurrencyWallet = { +on: Subscriber<EdgeCurrencyWalletEvents>; +watch: Subscriber<EdgeCurrencyWallet>; // Data store: +created: Date | void; +disklet: Disklet; +id: string; +localDisklet: Disklet; +publicWalletInfo: EdgeWalletInfo; +sync: () => Promise<void>; +type: string; // Wallet name: +name: string | null; +renameWallet: (name: string) => Promise<void>; // Fiat currency option: +fiatCurrencyCode: string; +setFiatCurrencyCode: (fiatCurrencyCode: string) => Promise<void>; // Currency info: +currencyConfig: EdgeCurrencyConfig; // eslint-disable-line no-use-before-define +currencyInfo: EdgeCurrencyInfo; // Chain state: +balanceMap: EdgeBalanceMap; +balances: EdgeBalances; +blockHeight: number; +syncRatio: number; +unactivatedTokenIds: string[]; // Running state: +changePaused: (paused: boolean) => Promise<void>; +paused: boolean; // Token management: // Available tokens can be found in `EdgeCurrencyConfig`. // This list is allowed to include missing or deleted `tokenIds`: +changeEnabledTokenIds: (tokenIds: string[]) => Promise<void>; +enabledTokenIds: string[]; /* Tokens detected on chain */ +detectedTokenIds: string[]; // Transaction history: +getNumTransactions: (opts: EdgeTokenIdOptions) => Promise<number>; +getTransactions: ( opts: EdgeGetTransactionsOptions, ) => Promise<EdgeTransaction[]>; +streamTransactions: ( opts: EdgeStreamTransactionOptions, ) => AsyncGenerator<EdgeTransaction[]>; // Addresses: +getAddresses: ( opts: EdgeGetReceiveAddressOptions, ) => Promise<EdgeAddress[]>; // Sending: +broadcastTx: (tx: EdgeTransaction) => Promise<EdgeTransaction>; +getMaxSpendable: (spendInfo: EdgeSpendInfo) => Promise<string>; +getPaymentProtocolInfo: ( paymentProtocolUrl: string, ) => Promise<EdgePaymentProtocolInfo>; +makeSpend: (spendInfo: EdgeSpendInfo) => Promise<EdgeTransaction>; +saveTx: (tx: EdgeTransaction) => Promise<void>; +saveTxAction: (opts: EdgeSaveTxActionOptions) => Promise<void>; +saveTxMetadata: (opts: EdgeSaveTxMetadataOptions) => Promise<void>; +signTx: (tx: EdgeTransaction) => Promise<EdgeTransaction>; +sweepPrivateKeys: ( edgeSpendInfo: EdgeSpendInfo, ) => Promise<EdgeTransaction>; // Signing: +signBytes: ( buf: Uint8Array, opts?: EdgeSignMessageOptions, ) => Promise<string>; // Accelerating: +accelerate: (tx: EdgeTransaction) => Promise<EdgeTransaction | null>; // Staking: +stakingStatus: EdgeStakingStatus; // Wallet management: +dumpData: () => Promise<EdgeDataDump>; +resyncBlockchain: () => Promise<void>; // URI handling: +encodeUri: (obj: EdgeEncodeUri) => Promise<string>; +parseUri: ( uri: string, currencyCode?: string, ) => Promise<EdgeParsedUri>; // Generic: +otherMethods: EdgeOtherMethods; /** @deprecated Use the information in EdgeCurrencyInfo / EdgeToken. */ +denominationToNative: ( denominatedAmount: string, currencyCode: string, ) => Promise<string>; /** @deprecated Use the information in EdgeCurrencyInfo / EdgeToken. */ +nativeToDenomination: ( nativeAmount: string, currencyCode: string, ) => Promise<string>; /** @deprecated Use `EdgeCurrencyWallet.getAddresses` instead */ +getReceiveAddress: ( opts: EdgeGetReceiveAddressOptions, ) => Promise<EdgeReceiveAddress>; /** @deprecated This was never implemented. */ +lockReceiveAddress: ( receiveAddress: EdgeReceiveAddress, ) => Promise<void>; /** @deprecated This was never implemented. */ +saveReceiveAddress: ( receiveAddress: EdgeReceiveAddress, ) => Promise<void>; /** @deprecated Use `signBytes` instead. */ +signMessage: ( message: string, opts?: EdgeSignMessageOptions, ) => Promise<string>; } export type EdgeMemoryWallet = { +watch: Subscriber<EdgeMemoryWallet>; +balanceMap: EdgeBalanceMap; +detectedTokenIds: string[]; +syncRatio: number; +changeEnabledTokenIds: (tokenIds: string[]) => Promise<void>; +startEngine: () => Promise<void>; +getMaxSpendable: (spendInfo: EdgeSpendInfo) => Promise<string>; +makeSpend: (spendInfo: EdgeSpendInfo) => Promise<EdgeTransaction>; +signTx: (tx: EdgeTransaction) => Promise<EdgeTransaction>; +broadcastTx: (tx: EdgeTransaction) => Promise<EdgeTransaction>; +saveTx: (tx: EdgeTransaction) => Promise<void>; +close: () => Promise<void>; } // --------------------------------------------------------------------- // swap plugin // --------------------------------------------------------------------- export type EdgeSwapPluginType = "DEX" | "CEX"; /** * Static data about a swap plugin. */ export type EdgeSwapInfo = { +pluginId: string; +displayName: string; +isDex?: boolean; /** @deprecated Use orderUri in EdgeTxAction */ +orderUri?: string; // The orderId would be appended to this +supportEmail: string; } export type EdgeSwapRequest = { // Where? fromWallet: EdgeCurrencyWallet; toWallet: EdgeCurrencyWallet; // What? fromTokenId: EdgeTokenId; toTokenId: EdgeTokenId; // How much? nativeAmount: string; quoteFor: "from" | "max" | "to"; } /** * If the user approves a quote, the plugin performs the transaction * and returns this as the result. */ export type EdgeSwapResult = { +orderId?: string; +destinationAddress?: string; +transaction: EdgeTransaction; } export type EdgeSwapApproveOptions = { metadata?: EdgeMetadata; savedAction?: EdgeTxAction; } /** * If a provider can satisfy a request, what is their price? */ export type EdgeSwapQuote = { +swapInfo: EdgeSwapInfo; +request: EdgeSwapRequest; +isEstimate: boolean; /** * This quote may be partially fulfilled with remaining source funds left * in wallet */ +canBePartial?: boolean; /** * Maximum amount of time this quote will take to be fulfilled (in seconds) */ +maxFulfillmentSeconds?: number; /** Worst-case receive amount */ +minReceiveAmount?: string; +fromNativeAmount: string; +toNativeAmount: string; +networkFee: EdgeTxAmount & { /** @deprecated use tokenId */ currencyCode: string; }; +pluginId: string; +expirationDate?: Date; +approve: (opts?: EdgeSwapApproveOptions) => Promise<EdgeSwapResult>; +close: () => Promise<void>; } export type EdgeSwapPluginStatus = { needsActivation?: boolean; } export type EdgeSwapPlugin = { +swapInfo: EdgeSwapInfo; +checkSettings?: (userSettings: JsonObject) => EdgeSwapPluginStatus; +fetchSwapQuote: ( request: EdgeSwapRequest, userSettings: JsonObject | void, opts: { infoPayload: JsonObject; promoCode?: string }, ) => Promise<EdgeSwapQuote>; } // --------------------------------------------------------------------- // account // --------------------------------------------------------------------- export type EdgeAccountOptions = { /** * If the login server returns a ChallengeError, * the user needs to visit the challenge URL and answer the question. * If the user succeeds, the challengeId will allow them to log in: */ challengeId?: string; /** * The current time, if different from `new Date()`. * Useful for unit testing. */ now?: Date; /** The user's OTP secret. */ otpKey?: string; /** A 6-digit OTP derived from the OTP secret. */ otp?: string; /** True to start wallets in the paused state. */ pauseWallets?: boolean; } /** * A pending request to log in from a new device. */ export type EdgePendingVoucher = { voucherId: string; activates: Date; created: Date; deviceDescription?: string; ip: string; ipDescription: string; } // credentials --------------------------------------------------------- export type ChangePinOptions = { /** Keeps the existing PIN if unspecified */ pin?: string; /** Defaults to true if unspecified */ enableLogin?: boolean; /** * True to configure the pin for the duress account. * Default is false. */ forDuressAccount?: boolean; } export type ChangeUsernameOptions = { username: string; /** * Changing the username requires passing the password, if present. * If the account has no password, providing this will create one. */ password?: string; } // currencies ---------------------------------------------------------- export type EdgeCreateCurrencyWalletOptions = { enabledTokenIds?: string[]; fiatCurrencyCode?: string; name?: string; // Create a private key from some text: importText?: string; // Used to tell the currency plugin what keys to create: keyOptions?: JsonObject; // Used to copy wallet keys between accounts: keys?: JsonObject; // Set if we are sweeping one wallet into another: migratedFromWalletId?: string; } export type EdgeCreateCurrencyWallet = EdgeCreateCurrencyWalletOptions & { walletType: string; }; export type EdgeCurrencyConfig = { +watch: Subscriber<EdgeCurrencyConfig>; +currencyInfo: EdgeCurrencyInfo; // Tokens: +allTokens: EdgeTokenMap; +builtinTokens: EdgeTokenMap; +customTokens: EdgeTokenMap; +getTokenDetails: ( filter: EdgeGetTokenDetailsFilter, ) => Promise<EdgeToken[]>; +getTokenId: (token: EdgeToken) => Promise<string>; +addCustomToken: (token: EdgeToken) => Promise<string>; +changeCustomToken: ( tokenId: string, token: EdgeToken, ) => Promise<void>; +removeCustomToken: (tokenId: string) => Promise<void>; // Always-enabled tokens: +alwaysEnabledTokenIds: string[]; +changeAlwaysEnabledTokenIds: (tokenIds: string[]) => Promise<void>; // User settings for this plugin: +userSettings: JsonObject | void; +changeUserSettings: (settings: JsonObject) => Promise<void>; // Utility methods: +importKey: ( userInput: string, opts?: { keyOptions?: JsonObject }, ) => Promise<JsonObject>; +otherMethods: EdgeOtherMethods; } // swap ---------------------------------------------------------------- /** * Information and settings for a currency swap plugin. */ export type EdgeSwapConfig = { +watch: Subscriber<EdgeSwapConfig>; +enabled: boolean; +needsActivation: boolean; +swapInfo: EdgeSwapInfo; +userSettings: JsonObject | void; +changeEnabled: (enabled: boolean) => Promise<void>; +changeUserSettings: (settings: JsonObject) => Promise<void>; } export type EdgeSwapRequestOptions = { preferPluginId?: string; preferType?: EdgeSwapPluginType; disabled?: EdgePluginMap<true>; promoCodes?: EdgePluginMap<string>; /** * If we have some quotes already, how long should we wait * for stragglers before we give up? Defaults to 20000ms. */ slowResponseMs?: number; /** * If don't have any quotes yet, how long should we wait * before we give up? Defaults to Infinity. */ noResponseMs?: number; } // edge login ---------------------------------------------------------- export type EdgeLoginRequest = { +appId: string; +displayName: string; +displayImageDarkUrl?: string; +displayImageLightUrl?: string; +approve: () => Promise<void>; +close: () => Promise<void>; } export type EdgeLobby = { +loginRequest: EdgeLoginRequest | void; // walletRequest: EdgeWalletRequest | void } // storage ------------------------------------------------------------- export type EdgeDataStore = { +deleteItem: (storeId: string, itemId: string) => Promise<void>; +deleteStore: (storeId: string) => Promise<void>; +listItemIds: (storeId: string) => Promise<string[]>; +listStoreIds: () => Promise<string[]>; +getItem: (storeId: string, itemId: string) => Promise<string>; +setItem: ( storeId: string, itemId: string, value: string, ) => Promise<void>; } // account ------------------------------------------------------------- export type EdgeAccountEvents = { close: void; } export type EdgeAccount = { +on: Subscriber<EdgeAccountEvents>; +watch: Subscriber<EdgeAccount>; // Data store: +id: string; +type: string; +disklet: Disklet; +localDisklet: Disklet; +sync: () => Promise<void>; // Basic login information: +appId: string; +created: Date | void; // Not always known +lastLogin: Date; +loggedIn: boolean; +recoveryKey: string | void; // base58, for email backup +rootLoginId: string; // base58 +username: string | void; // Duress mode: +canDuressLogin: boolean; +isDuressAccount: boolean; /** Gets the base58 decryption key for biometric login */ +getLoginKey: () => Promise<string>; // base58 // Special-purpose API's: +currencyConfig: EdgePluginMap<EdgeCurrencyConfig>; +swapConfig: EdgePluginMap<EdgeSwapConfig>; +dataStore: EdgeDataStore; // What login method was used? +edgeLogin: boolean; +keyLogin: boolean; +newAccount: boolean; +passwordLogin: boolean; +pinLogin: boolean; +recoveryLogin: boolean; // Change or create credentials: +changePassword: (password: string) => Promise<void>; +changePin: (opts: ChangePinOptions) => Promise<string>; +changeRecovery: ( questions: string[], answers: string[], ) => Promise<string>; +changeUsername: (opts: ChangeUsernameOptions) => Promise<void>; // Verify existing credentials: +checkPassword: (password: string) => Promise<boolean>; +checkPin: ( pin: string, opts?: { forDuressAccount?: boolean }, ) => Promise<boolean>; +getPin: () => Promise<string | void>; // Remove credentials: +deletePassword: () => Promise<void>; +deletePin: () => Promise<void>; +deleteRecovery: () => Promise<void>; // OTP: +otpKey: string | void; // OTP is enabled if this exists +otpResetDate: Date | void; // A reset is requested if this exists +cancelOtpReset: () => Promise<void>; +disableOtp: () => Promise<void>; +enableOtp: (timeout?: number) => Promise<void>; +repairOtp: (otpKey: string) => Promise<void>; // 2fa bypass voucher approval / rejection: +pendingVouchers: EdgePendingVoucher[]; +approveVoucher: (voucherId: string) => Promise<void>; +rejectVoucher: (voucherId: string) => Promise<void>; // Edge login approval: +fetchLobby: (lobbyId: string) => Promise<EdgeLobby>; // Login management: +deleteRemoteAccount: () => Promise<void>; +logout: () => Promise<void>; // Master wallet list: +allKeys: EdgeWalletInfoFull[]; +changeWalletStates: ( walletStates: EdgeWalletStates, ) => Promise<void>; +createWallet: (type: string, keys?: JsonObject) => Promise<string>; +getFirstWalletInfo: (type: string) => EdgeWalletInfoFull | void; +getWalletInfo: (id: string) => EdgeWalletInfoFull | void; +listWalletIds: () => string[]; +listSplittableWalletTypes: (walletId: string) => Promise<string[]>; +splitWalletInfo: ( walletId: string, newWalletType: string, ) => Promise<string>; // Key access: +getDisplayPrivateKey: (walletId: string) => Promise<string>; +getDisplayPublicKey: (walletId: string) => Promise<string>; +getRawPrivateKey: (walletId: string) => Promise<JsonObject>; +getRawPublicKey: (walletId: string) => Promise<JsonObject>; // Currency wallets: +activeWalletIds: string[]; +archivedWalletIds: string[]; +hiddenWalletIds: string[]; +currencyWallets: { [walletId: string]: EdgeCurrencyWallet }; +currencyWalletErrors: { [walletId: string]: Error }; +createCurrencyWallet: ( walletType: string, opts?: EdgeCreateCurrencyWalletOptions, ) => Promise<EdgeCurrencyWallet>; +createCurrencyWallets: ( createWallets: EdgeCreateCurrencyWallet[], ) => Promise<Array<EdgeResult<EdgeCurrencyWallet>>>; +waitForCurrencyWallet: ( walletId: string, ) => Promise<EdgeCurrencyWallet>; +waitForAllWallets: () => Promise<void>; +makeMemoryWallet: ( walletType: string, opts?: EdgeCreateCurrencyWalletOptions, ) => Promise<EdgeMemoryWallet>; // Token & wallet activation: +getActivationAssets: ( options: EdgeGetActivationAssetsOptions, ) => Promise<EdgeGetActivationAssetsResults>; +activateWallet: ( options: EdgeActivationOptions, ) => Promise<EdgeActivationQuote>; // Swapping: +fetchSwapQuote: ( request: EdgeSwapRequest, opts?: EdgeSwapRequestOptions, ) => Promise<EdgeSwapQuote>; +fetchSwapQuotes: ( request: EdgeSwapRequest, opts?: EdgeSwapRequestOptions, ) => Promise<EdgeSwapQuote[]>; } // --------------------------------------------------------------------- // context types // --------------------------------------------------------------------- export type EdgeCorePlugin = EdgeCurrencyPlugin | EdgeSwapPlugin; export type EdgeCorePluginFactory = ( env: EdgeCorePluginOptions, ) => EdgeCorePlugin; export type EdgeCorePlugins = EdgePluginMap< EdgeCorePlugin | EdgeCorePluginFactory >; export type EdgeCorePluginsInit = EdgePluginMap<boolean | JsonObject>; export type EdgeContextOptions = { apiKey?: string; apiSecret?: Uint8Array; appId: stri