edge-core-js 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -621,8 +621,8 @@ export function makeAccountApi(ai, accountId) {
621
621
  throw new Error(
622
622
  `activateWallet unsupported by walletId ${activateWalletId}`
623
623
  )
624
- const walletId = _optionalChain([paymentInfo, 'optionalAccess', _ => _.walletId])
625
- const wallet = currencyWallets[_nullishCoalesce(walletId, () => ( ''))]
624
+ const walletId = _nullishCoalesce(_optionalChain([paymentInfo, 'optionalAccess', _ => _.walletId]), () => ( ''))
625
+ const wallet = currencyWallets[walletId]
626
626
 
627
627
  if (wallet == null) {
628
628
  throw new Error(`No wallet for walletId ${walletId}`)
@@ -154,10 +154,7 @@ const accountPixie = combinePixies({
154
154
 
155
155
  return {
156
156
  update() {
157
- const { accountOutput } = input.props
158
- if (accountOutput == null) return
159
- const { accountApi } = accountOutput
160
- if (accountApi == null) return
157
+ if (_optionalChain([input, 'access', _ => _.props, 'access', _2 => _2.accountOutput, 'optionalAccess', _3 => _3.accountApi]) == null) return
161
158
 
162
159
  // Start once the EdgeAccount API exists:
163
160
  dataTask.start({ wait: true })
@@ -244,14 +241,14 @@ const accountPixie = combinePixies({
244
241
  lastActiveWalletIds = activeWalletIds
245
242
 
246
243
  let lastOut = {}
247
- if (_optionalChain([accountOutput, 'optionalAccess', _ => _.currencyWallets]) != null) {
244
+ if (_optionalChain([accountOutput, 'optionalAccess', _4 => _4.currencyWallets]) != null) {
248
245
  lastOut = accountOutput.currencyWallets
249
246
  }
250
247
 
251
248
  const out = {}
252
249
  const { wallets } = input.props.output.currency
253
250
  for (const walletId of activeWalletIds) {
254
- const api = _optionalChain([wallets, 'access', _2 => _2[walletId], 'optionalAccess', _3 => _3.walletApi])
251
+ const api = _optionalChain([wallets, 'access', _5 => _5[walletId], 'optionalAccess', _6 => _6.walletApi])
255
252
  if (api !== lastOut[walletId]) dirty = true
256
253
  if (api != null) out[walletId] = api
257
254
  }
@@ -37,9 +37,7 @@ export async function fetchAppIdInfo(
37
37
  appId
38
38
  ) {
39
39
  try {
40
- const infoServerUri = shuffle(
41
- ai.props.state.contextConfig.edgeServers.infoServers
42
- )[0]
40
+ const [infoServerUri] = shuffle(ai.props.state.infoServers)
43
41
  const url = `${infoServerUri}/v1/appIdInfo/${appId}`
44
42
  const response = await ai.props.io.fetch(url)
45
43
  if (response.status === 404) {
@@ -1,9 +1,21 @@
1
- import { combinePixies, stopUpdates, } from 'redux-pixies'
1
+ import {
2
+ combinePixies,
3
+ filterPixie,
4
+ stopUpdates,
5
+
6
+ } from 'redux-pixies'
2
7
  import { close, update } from 'yaob'
3
8
 
4
9
 
10
+ import { makePeriodicTask } from '../../util/periodic-task'
11
+ import { shuffle } from '../../util/shuffle'
5
12
 
6
13
  import { makeContextApi } from './context-api'
14
+ import {
15
+ asInfoCacheFile,
16
+ INFO_CACHE_FILE_NAME,
17
+ infoCacheFile
18
+ } from './info-cache-file'
7
19
 
8
20
 
9
21
 
@@ -41,5 +53,38 @@ export const context = combinePixies({
41
53
  }
42
54
  }
43
55
  }
44
- }
56
+ },
57
+
58
+ infoFetcher: filterPixie(
59
+ (input) => {
60
+ async function doInfoSync() {
61
+ const { dispatch, io } = input.props
62
+
63
+ const [infoServerUri] = shuffle(input.props.state.infoServers)
64
+ const response = await fetch(`${infoServerUri}/v1/coreRollup`, {
65
+ headers: { accept: 'application/json' }
66
+ })
67
+ if (!response.ok) return
68
+ const json = await response.json()
69
+
70
+ const infoCache = asInfoCacheFile(json)
71
+ dispatch({
72
+ type: 'INFO_CACHE_FETCHED',
73
+ payload: infoCache
74
+ })
75
+ await infoCacheFile.save(io.disklet, INFO_CACHE_FILE_NAME, infoCache)
76
+ }
77
+
78
+ const infoTask = makePeriodicTask(doInfoSync, 10 * 60 * 1000)
79
+ infoTask.start()
80
+
81
+ return {
82
+ update() {},
83
+ destroy() {
84
+ infoTask.stop()
85
+ }
86
+ }
87
+ },
88
+ props => (props.state.paused ? undefined : props)
89
+ )
45
90
  })
@@ -0,0 +1,18 @@
1
+ import { asArray, asObject, asString } from 'cleaners'
2
+
3
+
4
+ import { asJsonObject, makeJsonFile } from '../../util/file-helpers'
5
+
6
+
7
+
8
+
9
+
10
+
11
+ export const INFO_CACHE_FILE_NAME = 'infoCache.json'
12
+
13
+ export const asInfoCacheFile = asObject({
14
+ corePlugins: asObject(asJsonObject),
15
+ syncServers: asArray(asString)
16
+ })
17
+
18
+ export const infoCacheFile = makeJsonFile(asInfoCacheFile)
@@ -1,4 +1,6 @@
1
- import { combinePixies, mapPixie, } from 'redux-pixies'
1
+ 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 { combinePixies, mapPixie, } from 'redux-pixies'
2
+
3
+ import { matchJson } from '../../util/match-json'
2
4
 
3
5
 
4
6
  import {
@@ -21,5 +23,33 @@ export const currency = combinePixies({
21
23
  walletState: props.state.currency.wallets[walletId],
22
24
  walletOutput: props.output.currency.wallets[walletId]
23
25
  })
24
- )
26
+ ),
27
+
28
+ pluginUpdater(input) {
29
+ let lastInfo
30
+
31
+ return async () => {
32
+ const { infoCache, plugins } = input.props.state
33
+
34
+ // Bail out quickly if nothing has changed:
35
+ if (lastInfo === infoCache) return
36
+
37
+ // Update plugins after the first run:
38
+ if (lastInfo != null) {
39
+ for (const pluginId of Object.keys(plugins.currency)) {
40
+ const plugin = plugins.currency[pluginId]
41
+ const newPayload = _nullishCoalesce(_optionalChain([infoCache, 'access', _ => _.corePlugins, 'optionalAccess', _2 => _2[pluginId]]), () => ( {}))
42
+ const oldPayload = _nullishCoalesce(_optionalChain([lastInfo, 'access', _3 => _3.corePlugins, 'optionalAccess', _4 => _4[pluginId]]), () => ( {}))
43
+
44
+ if (
45
+ plugin.updateInfoPayload != null &&
46
+ !matchJson(oldPayload, newPayload)
47
+ ) {
48
+ await plugin.updateInfoPayload(newPayload)
49
+ }
50
+ }
51
+ }
52
+ lastInfo = infoCache
53
+ }
54
+ }
25
55
  })
@@ -30,11 +30,7 @@ import {
30
30
 
31
31
 
32
32
 
33
- import {
34
-
35
- mergeTx,
36
-
37
- } from './currency-wallet-reducer'
33
+ import { mergeTx, } from './currency-wallet-reducer'
38
34
  import { uniqueStrings } from './enabled-tokens'
39
35
 
40
36
  let throttleRateLimitMs = 5000
@@ -198,7 +194,7 @@ export function makeCurrencyWalletCallbacks(
198
194
  return
199
195
  }
200
196
  pushUpdate({
201
- id: `${walletId}==${tokenId}`,
197
+ id: `${walletId}==${String(tokenId)}`,
202
198
  action: 'onTokenBalanceChanged',
203
199
  updateFunc: () => {
204
200
  input.props.dispatch({
@@ -418,7 +414,7 @@ export function watchCurrencyWallet(input) {
418
414
  }
419
415
 
420
416
  export const validateConfirmations = (
421
- tx,
417
+ tx, // Either EdgeTransaction or MergedTransaction
422
418
  blockHeight,
423
419
  requiredConfirmations = 1 // Default confirmation rule is 1 block
424
420
  ) => {
@@ -235,23 +235,25 @@ export async function loadTokensFile(
235
235
  disklet,
236
236
  LEGACY_TOKENS_FILE
237
237
  )
238
- const { accountId, currencyInfo, pluginId } = input.props.walletState
239
- const accountState = input.props.state.accounts[accountId]
240
- const tokenIds = currencyCodesToTokenIds(
241
- accountState.builtinTokens[pluginId],
242
- accountState.customTokens[pluginId],
243
- currencyInfo,
244
- _nullishCoalesce(legacyCurrencyCodes, () => ( []))
245
- )
238
+ if (legacyCurrencyCodes != null) {
239
+ const { accountId, currencyInfo, pluginId } = input.props.walletState
240
+ const accountState = input.props.state.accounts[accountId]
241
+ const tokenIds = currencyCodesToTokenIds(
242
+ accountState.builtinTokens[pluginId],
243
+ accountState.customTokens[pluginId],
244
+ currencyInfo,
245
+ legacyCurrencyCodes
246
+ )
246
247
 
247
- dispatch({
248
- type: 'CURRENCY_WALLET_LOADED_TOKEN_FILE',
249
- payload: {
250
- walletId: input.props.walletId,
251
- detectedTokenIds: [],
252
- enabledTokenIds: tokenIds
253
- }
254
- })
248
+ dispatch({
249
+ type: 'CURRENCY_WALLET_LOADED_TOKEN_FILE',
250
+ payload: {
251
+ walletId: input.props.walletId,
252
+ detectedTokenIds: [],
253
+ enabledTokenIds: tokenIds
254
+ }
255
+ })
256
+ }
255
257
  }
256
258
 
257
259
  /**
@@ -7,8 +7,9 @@ export const asEdgeMetadata = raw => {
7
7
  const { exchangeAmount = {} } = clean
8
8
 
9
9
  // Delete corrupt amounts that exceed the Javascript number range:
10
- for (const fiat of Object.keys(clean)) {
10
+ for (const fiat of Object.keys(exchangeAmount)) {
11
11
  if (String(exchangeAmount[fiat]).includes('e')) {
12
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
12
13
  delete exchangeAmount[fiat]
13
14
  }
14
15
  }
@@ -30,9 +30,9 @@ export class FakeDb {
30
30
 
31
31
 
32
32
  constructor() {
33
- this.lobbies = {}
33
+ this.lobbies = new Map()
34
34
  this.logins = []
35
- this.repos = {}
35
+ this.repos = new Map()
36
36
  }
37
37
 
38
38
  getLoginById(loginId) {
@@ -80,7 +80,7 @@ export class FakeDb {
80
80
  }
81
81
 
82
82
  setupRepo(syncKey, repo) {
83
- this.repos[syncKey] = repo
83
+ this.repos.set(syncKey, repo)
84
84
  }
85
85
 
86
86
  dumpLogin(login) {
@@ -279,7 +279,7 @@ function createLogin(request, login) {
279
279
  keyBoxes: []
280
280
  }))(body.data)
281
281
  for (const syncKey of keys.newSyncKeys) {
282
- db.repos[syncKey] = {}
282
+ db.repos.set(syncKey, {})
283
283
  }
284
284
 
285
285
  // Start building the new database row:
@@ -326,7 +326,7 @@ const addKeysRoute = withLogin2(request => {
326
326
 
327
327
  // Set up repos:
328
328
  for (const syncKey of clean.newSyncKeys) {
329
- db.repos[syncKey] = {}
329
+ db.repos.set(syncKey, {})
330
330
  }
331
331
  login.keyBoxes = softCat(login.keyBoxes, clean.keyBoxes)
332
332
 
@@ -596,7 +596,7 @@ const withLobby =
596
596
  request => {
597
597
  const { db, path } = request
598
598
  const lobbyId = path.split('/')[4]
599
- const lobby = db.lobbies[lobbyId]
599
+ const lobby = db.lobbies.get(lobbyId)
600
600
  return lobby != null
601
601
  ? server({ ...request, lobby, lobbyId })
602
602
  : fallback({ ...request, lobbyId })
@@ -619,7 +619,7 @@ const createLobbyRoute = withLobby(
619
619
  const { timeout = 600 } = clean
620
620
  const expires = new Date(Date.now() + 1000 * timeout).toISOString()
621
621
 
622
- db.lobbies[lobbyId] = { request: clean, replies: [], expires }
622
+ db.lobbies.set(lobbyId, { request: clean, replies: [], expires })
623
623
  return statusResponse()
624
624
  }
625
625
  )
@@ -643,7 +643,7 @@ const getLobbyRoute = withLobby(request => {
643
643
 
644
644
  const deleteLobbyRoute = withLobby(request => {
645
645
  const { db, lobbyId } = request
646
- delete db.lobbies[lobbyId]
646
+ db.lobbies.delete(lobbyId)
647
647
  return statusResponse()
648
648
  })
649
649
 
@@ -682,7 +682,7 @@ const withRepo =
682
682
  const syncKey = elements[4]
683
683
  // const hash = elements[5]
684
684
 
685
- const repo = db.repos[syncKey]
685
+ const repo = db.repos.get(syncKey)
686
686
  if (repo == null) {
687
687
  // This is not the auth server, so we have a different format:
688
688
  return jsonResponse({ msg: 'Hash not found' }, { status: 404 })
@@ -158,7 +158,9 @@ export function makeFakeWorld(
158
158
 
159
159
  // Find the data on the server:
160
160
  const login = fakeDb.getLoginById(loginId)
161
- if (login == null) throw new Error(`Cannot find user ${account.username}`)
161
+ if (login == null) {
162
+ throw new Error(`Cannot find user ${account.rootLoginId}`)
163
+ }
162
164
 
163
165
  // Figure out which repos to use:
164
166
  const syncKeys = []
@@ -171,7 +173,8 @@ export function makeFakeWorld(
171
173
  }
172
174
  const repos = {}
173
175
  for (const syncKey of syncKeys) {
174
- repos[syncKey] = wasEdgeRepoDump(fakeDb.repos[syncKey])
176
+ const repo = fakeDb.repos.get(syncKey)
177
+ if (repo != null) repos[syncKey] = wasEdgeRepoDump(repo)
175
178
  }
176
179
 
177
180
  return {
@@ -1,4 +1,5 @@
1
- import { navigateDisklet } from 'disklet'
1
+ 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 { navigateDisklet } from 'disklet'
2
+
2
3
 
3
4
 
4
5
 
@@ -35,7 +36,7 @@ export function addEdgeCorePlugins(plugins) {
35
36
  }
36
37
 
37
38
  // Save the new plugins:
38
- for (const pluginId in plugins) {
39
+ for (const pluginId of Object.keys(plugins)) {
39
40
  allPlugins[pluginId] = plugins[pluginId]
40
41
  }
41
42
 
@@ -56,6 +57,7 @@ export function lockEdgeCorePlugins() {
56
57
  */
57
58
  export function watchPlugins(
58
59
  ios,
60
+ infoCache,
59
61
  logBackend,
60
62
  pluginsInit,
61
63
  dispatch
@@ -66,7 +68,7 @@ export function watchPlugins(
66
68
  function pluginsAdded(plugins) {
67
69
  const out = {}
68
70
 
69
- for (const pluginId in plugins) {
71
+ for (const pluginId of Object.keys(plugins)) {
70
72
  const plugin = plugins[pluginId]
71
73
  const log = makeLog(logBackend, pluginId)
72
74
  const initOptions = pluginsInit[pluginId]
@@ -76,6 +78,7 @@ export function watchPlugins(
76
78
  try {
77
79
  if (typeof plugin === 'function') {
78
80
  const opts = {
81
+ infoPayload: _nullishCoalesce(_optionalChain([infoCache, 'access', _ => _.corePlugins, 'optionalAccess', _2 => _2[pluginId]]), () => ( {})),
79
82
  initOptions: typeof initOptions === 'object' ? initOptions : {},
80
83
  io: legacyIo,
81
84
  log,
@@ -70,7 +70,7 @@ export async function waitForPlugins(ai) {
70
70
 
71
71
  const { currency, swap } = props.state.plugins
72
72
  const missingPlugins = []
73
- for (const pluginId in init) {
73
+ for (const pluginId of Object.keys(init)) {
74
74
  const shouldLoad = init[pluginId] !== false && init[pluginId] != null
75
75
  if (shouldLoad && currency[pluginId] == null && swap[pluginId] == null) {
76
76
  missingPlugins.push(pluginId)
@@ -3,7 +3,7 @@ import { buildReducer, mapReducer } from 'redux-keto'
3
3
 
4
4
  import { accountReducer, } from './account/account-reducer'
5
5
 
6
- import { contextConfig, } from './context/context-reducer'
6
+
7
7
  import { currency, } from './currency/currency-reducer'
8
8
  import { login, } from './login/login-reducer'
9
9
  import { plugins, } from './plugins/plugins-reducer'
@@ -26,6 +26,8 @@ import { storageWallets, } from './storage/storage-reducer'
26
26
 
27
27
 
28
28
 
29
+
30
+
29
31
 
30
32
 
31
33
  export const defaultLogSettings = {
@@ -64,6 +66,20 @@ export const reducer = buildReducer({
64
66
  return action.type === 'INIT' ? action.payload.hideKeys : state
65
67
  },
66
68
 
69
+ infoCache(state = {}, action) {
70
+ switch (action.type) {
71
+ case 'INIT':
72
+ return action.payload.infoCache
73
+ case 'INFO_CACHE_FETCHED':
74
+ return action.payload
75
+ }
76
+ return state
77
+ },
78
+
79
+ infoServers(state = [], action) {
80
+ return action.type === 'INIT' ? action.payload.infoServers : state
81
+ },
82
+
67
83
  lastAccountId(state, action, next) {
68
84
  return `login${next.accountCount}`
69
85
  },
@@ -90,7 +106,10 @@ export const reducer = buildReducer({
90
106
  return action.type === 'INIT' ? action.payload.skipBlockHeight : state
91
107
  },
92
108
 
93
- contextConfig,
109
+ syncServers(state = [], action) {
110
+ return action.type === 'INIT' ? action.payload.syncServers : state
111
+ },
112
+
94
113
  currency,
95
114
  login,
96
115
  plugins,
package/lib/core/root.js CHANGED
@@ -7,6 +7,7 @@ import { emit } from 'yaob'
7
7
  import { validateServer } from '../util/validateServer'
8
8
 
9
9
  import { CLIENT_FILE_NAME, clientFile } from './context/client-file'
10
+ import { INFO_CACHE_FILE_NAME, infoCacheFile } from './context/info-cache-file'
10
11
  import { filterLogs, makeLog } from './log/log'
11
12
  import { loadStashes } from './login/login-stash'
12
13
  import { watchPlugins } from './plugins/plugins-actions'
@@ -35,23 +36,33 @@ export async function makeContext(
35
36
  apiKey,
36
37
  appId = '',
37
38
  authServer = 'https://login.edge.app/api',
38
- infoServer = ['https://info-eu1.edge.app', 'https://info-us1.edge.app'],
39
- syncServer = [
40
- 'https://sync-us1.edge.app',
41
- 'https://sync-us2.edge.app',
42
- 'https://sync-us3.edge.app',
43
- 'https://sync-us4.edge.app',
44
- 'https://sync-us5.edge.app',
45
- 'https://sync-us6.edge.app',
46
- 'https://sync-eu.edge.app'
47
- ],
39
+ infoServer,
40
+ syncServer,
48
41
  deviceDescription = null,
49
42
  hideKeys = false,
50
43
  plugins: pluginsInit = {},
51
44
  skipBlockHeight = false
52
45
  } = opts
53
- const infoServers = Array.isArray(infoServer) ? infoServer : [infoServer]
54
- const syncServers = Array.isArray(syncServer) ? syncServer : [syncServer]
46
+ const infoServers =
47
+ typeof infoServer === 'string'
48
+ ? [infoServer]
49
+ : infoServer != null && infoServer.length > 0
50
+ ? infoServer
51
+ : ['https://info-eu1.edge.app', 'https://info-us1.edge.app']
52
+ const syncServers =
53
+ typeof syncServer === 'string'
54
+ ? [syncServer]
55
+ : syncServer != null && syncServer.length > 0
56
+ ? syncServer
57
+ : [
58
+ 'https://sync-us1.edge.app',
59
+ 'https://sync-us2.edge.app',
60
+ 'https://sync-us3.edge.app',
61
+ 'https://sync-us4.edge.app',
62
+ 'https://sync-us5.edge.app',
63
+ 'https://sync-us6.edge.app',
64
+ 'https://sync-eu.edge.app'
65
+ ]
55
66
  const logSettings = { ...defaultLogSettings, ...opts.logSettings }
56
67
  if (apiKey == null) {
57
68
  throw new Error('No API key provided')
@@ -71,21 +82,26 @@ export async function makeContext(
71
82
  })
72
83
  const log = makeLog(logBackend, 'edge-core')
73
84
 
74
- // Load the clientId from disk:
75
- let clientInfo = await clientFile.load(io.disklet, CLIENT_FILE_NAME)
85
+ let [clientInfo, infoCache = {}, stashes] = await Promise.all([
86
+ clientFile.load(io.disklet, CLIENT_FILE_NAME),
87
+ infoCacheFile.load(io.disklet, INFO_CACHE_FILE_NAME),
88
+ loadStashes(io.disklet, log)
89
+ ])
90
+
91
+ // Save the clientId if we don't have one:
76
92
  if (clientInfo == null) {
77
93
  clientInfo = { clientId: io.random(16) }
78
94
  await clientFile.save(io.disklet, CLIENT_FILE_NAME, clientInfo)
79
95
  }
80
96
 
81
97
  // Load the login stashes from disk:
82
- const stashes = await loadStashes(io.disklet, log)
83
98
  redux.dispatch({
84
99
  type: 'INIT',
85
100
  payload: {
86
101
  apiKey,
87
102
  appId,
88
103
  authServer,
104
+ infoCache,
89
105
  infoServers,
90
106
  syncServers,
91
107
  clientId: clientInfo.clientId,
@@ -101,13 +117,14 @@ export async function makeContext(
101
117
  // Subscribe to new plugins:
102
118
  const closePlugins = watchPlugins(
103
119
  ios,
120
+ infoCache,
104
121
  logBackend,
105
122
  pluginsInit,
106
123
  redux.dispatch
107
124
  )
108
125
 
109
126
  // Create sync client:
110
- const syncClient = await makeSyncClient({
127
+ const syncClient = makeSyncClient({
111
128
  log,
112
129
  fetch: io.fetch,
113
130
  edgeServers: { infoServers, syncServers }
@@ -43,9 +43,9 @@ export async function addStorageWallet(
43
43
  const { syncKey } = walletInfo.keys
44
44
  const { lastHash } = status
45
45
  ai.props.log.error(
46
- `Could not sync ${syncKey} with last hash ${String(lastHash)}: ${String(
47
- error
48
- )}`
46
+ `Could not sync ${String(syncKey)} with last hash ${String(
47
+ lastHash
48
+ )}: ${String(error)}`
49
49
  )
50
50
  onError(error)
51
51
  })
@@ -1,4 +1,4 @@
1
- function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }import { gt, lt } from 'biggystring'
1
+ 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 { gt, lt } from 'biggystring'
2
2
  import { bridgifyObject, close } from 'yaob'
3
3
 
4
4
  import {
@@ -33,11 +33,11 @@ export async function fetchSwapQuotes(
33
33
  promoCodes = {},
34
34
  slowResponseMs = 20000
35
35
  } = opts
36
- const { log } = ai.props
36
+ const { log, state } = ai.props
37
37
 
38
- const account = ai.props.state.accounts[accountId]
38
+ const account = state.accounts[accountId]
39
39
  const { swapSettings, userSettings } = account
40
- const swapPlugins = ai.props.state.plugins.swap
40
+ const swapPlugins = state.plugins.swap
41
41
 
42
42
  log.warn(
43
43
  'Requesting swap quotes for: ',
@@ -62,6 +62,7 @@ export async function fetchSwapQuotes(
62
62
  promises.push(
63
63
  swapPlugins[pluginId]
64
64
  .fetchSwapQuote(request, userSettings[pluginId], {
65
+ infoPayload: _nullishCoalesce(_optionalChain([state, 'access', _ => _.infoCache, 'access', _2 => _2.corePlugins, 'optionalAccess', _3 => _3[pluginId]]), () => ( {})),
65
66
  promoCode: promoCodes[pluginId]
66
67
  })
67
68
  .then(
package/lib/flow/types.js CHANGED
@@ -165,9 +165,12 @@ export type EdgeNativeIo = {
165
165
  * All core plugins receive these options at creation time.
166
166
  */
167
167
  export type EdgeCorePluginOptions = {
168
- // Load-time options (like API keys) passed into the context:
168
+ /** Load-time options (like API keys) passed into the context */
169
169
  initOptions: JsonObject;
170
170
 
171
+ /** Data provided by the info server */
172
+ infoPayload: JsonObject;
173
+
171
174
  // Access to the world outside the plugin:
172
175
  io: EdgeIo;
173
176
  log: EdgeLog; // Plugin-scoped logging
@@ -1040,6 +1043,7 @@ export type EdgeCurrencyPlugin = {
1040
1043
  walletInfo: EdgeWalletInfo,
1041
1044
  opts: EdgeCurrencyEngineOptions,
1042
1045
  ) => Promise<EdgeCurrencyEngine>;
1046
+ +updateInfoPayload?: (infoPayload: JsonObject) => Promise<void>;
1043
1047
 
1044
1048
  // Escape hatch:
1045
1049
  +otherMethods?: EdgeOtherMethods;
@@ -1317,7 +1321,7 @@ export type EdgeSwapPlugin = {
1317
1321
  +fetchSwapQuote: (
1318
1322
  request: EdgeSwapRequest,
1319
1323
  userSettings: JsonObject | void,
1320
- opts: { promoCode?: string },
1324
+ opts: { infoPayload: JsonObject; promoCode?: string },
1321
1325
  ) => Promise<EdgeSwapQuote>;
1322
1326
  }
1323
1327
 
@@ -76,6 +76,7 @@ function makePendingList() {
76
76
  grab(id) {
77
77
  const call = map[String(id)]
78
78
  if (call == null) return dummyCall
79
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
79
80
  delete map[String(id)]
80
81
  return call
81
82
  }