UNPKG

edge-core-js

Version:

Edge account & wallet management library

202 lines (173 loc) 6.04 kB
function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }import { makeMemoryDisklet } from 'disklet' import { bridgifyObject, close, update, watchMethod } from 'yaob' import { makePeriodicTask, } from '../../util/periodic-task' import { snooze } from '../../util/snooze' import { getMaxSpendableInner } from '../currency/wallet/max-spend' import { makeLog } from '../log/log' import { getCurrencyTools } from '../plugins/plugins-selectors' let memoryWalletCount = 0 export const makeMemoryWalletInner = async ( ai, config, walletType, opts = {} ) => { const { keys } = opts if (keys == null) throw new Error('No keys provided') const walletId = `memorywallet-${memoryWalletCount++}` const walletInfo = { id: walletId, type: walletType, keys } const tools = await getCurrencyTools(ai, config.currencyInfo.pluginId) const publicKeys = await tools.derivePublicKey(walletInfo) walletInfo.keys = { ...publicKeys, ...walletInfo.keys } const log = makeLog(ai.props.logBackend, `${walletId}-${walletType}`) let balanceMap = new Map() let detectedTokenIds = [] let syncRatio = 0 let needsUpdate = false const updateWallet = () => { if (needsUpdate) { update(out) needsUpdate = false } } const updater = makePeriodicTask(async () => { await snooze(1000) // one second updateWallet() }, 0) const plugin = ai.props.state.plugins.currency[config.currencyInfo.pluginId] const engine = await plugin.makeCurrencyEngine(walletInfo, { callbacks: { onAddressChanged: () => {}, onAddressesChecked: (progressRatio) => { if (out.syncRatio === 1) return if (progressRatio === 1) { syncRatio = progressRatio needsUpdate = true } }, onNewTokens: (tokenIds) => { const sortedTokenIds = tokenIds.sort((a, b) => a.localeCompare(b)) if (detectedTokenIds.length !== sortedTokenIds.length) { detectedTokenIds = sortedTokenIds needsUpdate = true return } for (let i = 0; i < sortedTokenIds.length; i++) { if (detectedTokenIds[i] !== sortedTokenIds[i]) { detectedTokenIds = sortedTokenIds needsUpdate = true return } } }, onSeenTxCheckpoint: () => {}, onStakingStatusChanged: () => {}, onSubscribeAddresses: () => {}, onTokenBalanceChanged: (tokenId, balance) => { if (balanceMap.get(tokenId) === balance) return balanceMap = new Map(balanceMap) balanceMap.set(tokenId, balance) needsUpdate = true }, onTransactions: () => {}, onTransactionsChanged: () => {}, onTxidsChanged: () => {}, onUnactivatedTokenIdsChanged: () => {}, onWcNewContractCall: () => {}, onBlockHeightChanged: () => {}, onBalanceChanged: () => {} }, customTokens: { ...config.customTokens }, enabledTokenIds: [...Object.keys(config.allTokens)], lightMode: true, log, userSettings: { ...(_nullishCoalesce(config.userSettings, () => ( {}))) }, walletLocalDisklet: makeMemoryDisklet(), walletLocalEncryptedDisklet: makeMemoryDisklet() }) const { unsafeBroadcastTx = false, unsafeMakeSpend = false, unsafeSyncNetwork = false } = plugin.currencyInfo const privateKeys = { ...keys } let syncNetworkTask // Setup syncNetwork routine if defined by the currency engine: if (engine.syncNetwork != null) { // Get the private keys if required by the engine: const doNetworkSync = async () => { if (engine.syncNetwork != null) { const delay = await engine.syncNetwork({ privateKeys: unsafeSyncNetwork ? { privateKeys: keys } : undefined }) syncNetworkTask.setDelay(delay) } else { syncNetworkTask.stop() } } syncNetworkTask = makePeriodicTask(doNetworkSync, 10000, { onError: error => { ai.props.log.error(error) } }) syncNetworkTask.start({ wait: false }) } const out = bridgifyObject({ watch: watchMethod, get balanceMap() { return balanceMap }, get detectedTokenIds() { return detectedTokenIds }, get syncRatio() { return syncRatio }, async changeEnabledTokenIds(tokenIds) { if (engine.changeEnabledTokenIds != null) { await engine.changeEnabledTokenIds(tokenIds) } }, async startEngine() { await engine.startEngine() _optionalChain([syncNetworkTask, 'optionalAccess', _ => _.start, 'call', _2 => _2({ wait: false })]) }, async getMaxSpendable(spendInfo) { return await getMaxSpendableInner( spendInfo, plugin, engine, config.allTokens, walletInfo ) }, async makeSpend(spendInfo) { return await engine.makeSpend( spendInfo, unsafeMakeSpend ? privateKeys : undefined ) }, async signTx(tx) { return await engine.signTx(tx, privateKeys) }, async broadcastTx(tx) { return await engine.broadcastTx( tx, unsafeBroadcastTx ? privateKeys : undefined ) }, async saveTx() {}, async close() { log.warn('killing memory wallet') _optionalChain([syncNetworkTask, 'optionalAccess', _3 => _3.stop, 'call', _4 => _4()]) close(out) await engine.killEngine() } }) updater.start({ wait: false }) return out }