New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@exodus/address-provider

Package Overview
Dependencies
Maintainers
0
Versions
73
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@exodus/address-provider - npm Package Compare versions

Comparing version 11.2.0 to 11.3.0

11

CHANGELOG.md

@@ -6,2 +6,13 @@ # Change Log

## [11.3.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/address-provider@11.2.0...@exodus/address-provider@11.3.0) (2024-07-16)
### Features
- add full key identifier to address meta ([#7595](https://github.com/ExodusMovement/exodus-hydra/issues/7595)) ([ebb8456](https://github.com/ExodusMovement/exodus-hydra/commit/ebb84561f24030af723714a9cf29e4a82fedf6a1))
### Bug Fixes
- fall back to mocked address for default path params/purpose ([#7684](https://github.com/ExodusMovement/exodus-hydra/issues/7684)) ([e3a00bd](https://github.com/ExodusMovement/exodus-hydra/commit/e3a00bdd38464b75c563f8ad36d260384362e816))
- use key identifier with enumerable derivation path ([#7854](https://github.com/ExodusMovement/exodus-hydra/issues/7854)) ([afd9653](https://github.com/ExodusMovement/exodus-hydra/commit/afd96533198a870568a83c4ecf03ead17d7797c1))
## [11.2.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/address-provider@11.1.0...@exodus/address-provider@11.2.0) (2024-07-08)

@@ -8,0 +19,0 @@

35

module/address-provider.js

@@ -95,4 +95,3 @@ import { Address, AddressSet } from '@exodus/models'

const keyId = new KeyIdentifier(keyIdArgs)
const keyIdentifier = new KeyIdentifier(keyIdArgs)
const canUseCache = !asset.api.features?.abstractAccounts

@@ -102,13 +101,16 @@ const cached =

? await this.#addressCache.get({
walletAccountName: walletAccount.toString(),
walletAccountName,
baseAssetName: asset.baseAsset.name,
derivationPath: keyId.derivationPath,
derivationPath: keyIdentifier.derivationPath,
})
: undefined
const { purpose: derivedPurpose } = parseDerivationPath(keyId.derivationPath)
const { purpose: derivedPurpose } = parseDerivationPath(keyIdentifier.derivationPath)
if (cached) {
const path = createPath({ chainIndex, addressIndex })
return Address.fromJSON({ meta: { path, purpose: derivedPurpose }, ...cached })
return Address.fromJSON({
meta: { path, purpose: derivedPurpose, keyIdentifier, walletAccount: walletAccountName },
...cached,
})
}

@@ -119,3 +121,3 @@

asset,
keyIdentifier: keyId,
keyIdentifier,
purpose: derivedPurpose,

@@ -135,3 +137,3 @@ chainIndex,

baseAssetName: asset.baseAsset.name,
derivationPath: keyId.derivationPath,
derivationPath: keyIdentifier.derivationPath,
address,

@@ -152,2 +154,4 @@ })

}) => {
const walletAccountName = walletAccount.toString()
if (asset.api.features?.abstractAccounts) {

@@ -157,3 +161,5 @@ const accountName = await this.#getMainAccountName({ walletAccount, assetName: asset.name })

path: createPath({ chainIndex, addressIndex }),
walletAccount: walletAccountName,
purpose,
keyIdentifier,
})

@@ -163,3 +169,3 @@ }

const publicKey = await this.#publicKeyProvider.getPublicKey({
walletAccount: walletAccount.toString(),
walletAccount: walletAccountName,
keyIdentifier,

@@ -181,3 +187,3 @@ })

stakingPublicKey = await this.#publicKeyProvider.getPublicKey({
walletAccount: walletAccount.toString(),
walletAccount: walletAccountName,
keyIdentifier: stakingKeyIdentifier,

@@ -192,3 +198,5 @@ })

path: createPath({ chainIndex, addressIndex }),
walletAccount: walletAccountName,
purpose,
keyIdentifier,
})

@@ -205,8 +213,9 @@ }

}) => {
const walletAccountName = walletAccount.toString()
const [publicKey, multisigData] = await Promise.all([
this.#publicKeyProvider.getPublicKey({
walletAccount: walletAccount.toString(),
walletAccount: walletAccountName,
keyIdentifier,
}),
this.#multisigAtom.get().then((s) => s[walletAccount.toString()]),
this.#multisigAtom.get().then((s) => s[walletAccountName]),
])

@@ -235,3 +244,5 @@

path: createPath({ chainIndex, addressIndex }),
walletAccount: walletAccountName,
purpose,
keyIdentifier,
spendingInfo: {

@@ -238,0 +249,0 @@ redeem,

@@ -66,3 +66,3 @@ import typeforce from '@exodus/typeforce'

const asset = this.#getAsset(assetName)
return getAddressesFromTxLog({ asset, txLog })
return getAddressesFromTxLog({ asset, txLog, walletAccount })
})

@@ -69,0 +69,0 @@

import addressCacheMemoryModuleDefinition from '@exodus/address-cache/module/memory'
import { set, isNil } from '@exodus/basic-utils'
import assert from 'minimalistic-assert'
import { Address, WalletAccount } from '@exodus/models'
import lodash from 'lodash'
import { isNil } from '@exodus/basic-utils'
import { get, merge } from 'lodash'
import { AddressProvider } from './address-provider'
import { createPath } from './utils'
import { getDefaultPathIndexes } from '../utils'
import KeyIdentifier from '@exodus/key-identifier'
const { get, merge } = lodash
const getPath = ({ walletAccount, asset, purpose, chainIndex, addressIndex }) => [
walletAccount.toString(),
asset.baseAsset?.name || asset.name,
[purpose, chainIndex, addressIndex].join('/'),
'address',
]
class MockableAddressProvider extends AddressProvider {

@@ -33,90 +24,131 @@ #assetsModule

async #getMockAddress({ purpose, assetName, walletAccount, chainIndex, addressIndex }) {
const hasIndex = !isNil(addressIndex) && !isNil(chainIndex)
const hasPurpose = !isNil(purpose)
const asset = this.#getAsset(assetName)
const walletAccountName = walletAccount.toString()
const mockAddresses = await this.#storage.get('mockableAddressProvider')
return get(
mockAddresses?.addresses,
getPath({ walletAccount, asset, purpose, chainIndex, addressIndex })
const keyIdentifier = new KeyIdentifier(
asset.baseAsset.api.getKeyIdentifier({
purpose,
accountIndex: walletAccount.index,
chainIndex,
addressIndex,
compatibilityMode: walletAccount.compatibilityMode,
})
)
if (hasPurpose && hasIndex) {
const address = get(mockAddresses?.addresses, [
walletAccountName,
asset.baseAsset?.name || assetName,
`${purpose}/${chainIndex}/${addressIndex}`,
'address',
])
if (address) {
return new Address(address, {
path: createPath({ chainIndex, addressIndex }),
purpose,
walletAccount: walletAccountName,
keyIdentifier,
})
}
}
if (hasPurpose) {
const address = get(mockAddresses?.addresses, [
walletAccountName,
asset.baseAsset?.name || assetName,
`${purpose}`,
'address',
])
if (address)
return new Address(address, {
purpose,
walletAccount: walletAccountName,
keyIdentifier,
})
}
const address = get(mockAddresses?.addresses, [
walletAccountName,
asset.baseAsset?.name || assetName,
'address',
])
if (address) {
return new Address(address, {
purpose: purpose ?? (await this.getDefaultPurpose({ walletAccount, assetName })),
walletAccount: walletAccountName,
keyIdentifier,
})
}
}
#normalizeOptions = async (opts) => {
let {
walletAccount = WalletAccount.DEFAULT_NAME,
purpose,
assetName,
chainIndex,
addressIndex,
} = opts
getAddress = async (opts) => {
let { purpose, assetName, walletAccount, chainIndex, addressIndex } = opts
assert(!isNil(walletAccount), `need to specify a walletAccount`)
assert(!isNil(assetName), `need to specify an asset`)
// not required with some compatibility modes, e.g. 'xverse'
assert(
!isNil(chainIndex) || isNil(addressIndex),
'chainIndex must be provided if addressIndex is provided'
'provide both "chainIndex" and "addressIndex" or neither'
)
const mockAddress = await this.#getMockAddress(opts)
if (mockAddress) return mockAddress
purpose = purpose ?? (await this.getDefaultPurpose({ walletAccount, assetName }))
if (isNil(addressIndex) && isNil(chainIndex)) {
const asset = this.#getAsset(assetName)
;({ chainIndex, addressIndex } = getDefaultPathIndexes({ asset }))
}
return { purpose, assetName, walletAccount, chainIndex, addressIndex }
return super.getAddress({ ...opts, purpose })
}
getAddress = async (opts) => {
opts = await this.#normalizeOptions(opts)
const mockAddressString = await this.#getMockAddress(opts)
mockAddress = async ({
walletAccount = WalletAccount.DEFAULT_NAME,
assetName,
address,
purpose,
chainIndex,
addressIndex,
}) => {
assert(!isNil(walletAccount), `need to specify a walletAccount`)
assert(!isNil(assetName), `need to specify an asset`)
assert(!isNil(address), `need to specify an address`)
assert(
!isNil(chainIndex) || isNil(addressIndex),
'chainIndex must be provided if addressIndex is provided'
)
const hasIndex = !isNil(addressIndex) && !isNil(chainIndex)
const hasPurpose = !isNil(purpose)
if (mockAddressString) {
const { purpose, chainIndex, addressIndex } = opts
return new Address(mockAddressString, {
path: createPath({ chainIndex, addressIndex }),
purpose,
})
const currentConfig = await this.#storage.get('mockableAddressProvider')
let newAddress
if (hasPurpose && hasIndex) {
const key = `${purpose}/${chainIndex}/${addressIndex}`
newAddress = { [walletAccount]: { [assetName]: { [key]: { address } } } }
} else if (hasPurpose) {
newAddress = { [walletAccount]: { [assetName]: { [purpose]: { address } } } }
} else {
newAddress = { [walletAccount]: { [assetName]: { address } } }
}
return super.getAddress(opts)
const newConfig = merge({}, currentConfig, { addresses: newAddress })
await this.#storage.set('mockableAddressProvider', newConfig)
}
mockAddress = async ({ address, ...opts }) => {
const {
walletAccount = WalletAccount.DEFAULT_NAME,
assetName,
purpose,
chainIndex,
addressIndex,
} = await this.#normalizeOptions(opts)
const asset = this.#getAsset(assetName)
const currentConfig =
(await this.#storage.get('mockableAddressProvider')) ?? Object.create(null)
const newConfig = { addresses: Object.create(null) }
set(
newConfig.addresses,
getPath({ walletAccount, asset, purpose, chainIndex, addressIndex }),
address.toString()
)
await this.#storage.set(
'mockableAddressProvider',
merge(Object.create(null), currentConfig, newConfig)
)
}
importReport = async (report) => {
const addresses = Object.create(null)
for (const walletAccount in report) {
addresses[walletAccount] = Object.create(null)
for (const assetName in report[walletAccount]) {
const asset = this.#getAsset(assetName)
addresses[walletAccount][assetName] = Object.create(null)
for (const bip in report[walletAccount][assetName]) {
const { address, chain: [chainIndex, addressIndex] = [0, 0] } =
report[walletAccount][assetName][bip]
const { address } = report[walletAccount][assetName][bip]
const purposeStr = bip.replace(/^bip/, '')
if (isNaN(purposeStr)) throw new Error(`Invalid bip: ${bip}`)
const purpose = parseInt(purposeStr, 10)
const path = getPath({ walletAccount, asset, purpose, chainIndex, addressIndex })
set(addresses, path, address)
// The report only has a single address per purpose.
// This will cause all chainIndex/addressIndex pairs to fall back to the same address.
addresses[walletAccount][assetName][purposeStr] = { address }
}

@@ -123,0 +155,0 @@ }

@@ -1,2 +0,2 @@

import { AddressSet } from '@exodus/models'
import { Address, AddressSet } from '@exodus/models'
import lodash from 'lodash'

@@ -6,2 +6,3 @@ import assert from 'minimalistic-assert'

import { isNil } from '@exodus/basic-utils'
import KeyIdentifier from '@exodus/key-identifier'

@@ -47,3 +48,3 @@ const { groupBy } = lodash

export const getAddressesFromTxLog = ({ asset, txLog }) => {
export const getAddressesFromTxLog = ({ asset, txLog, walletAccount }) => {
const changeAddresses = AddressSet.fromArray(

@@ -57,8 +58,27 @@ [...txLog].map((tx) => tx.data?.changeAddress).filter(Boolean)

return [...allAddresses].map((address) => ({
address,
purpose: resolvePurpose({ asset, address }),
chainIndex: address.pathArray[0],
addressIndex: address.pathArray[1],
}))
return [...allAddresses].map((address) => {
const purpose = resolvePurpose({ asset, address })
const chainIndex = address.pathArray[0]
const addressIndex = address.pathArray[1]
return {
address: new Address(address.toString(), {
...address.meta,
purpose,
walletAccount: walletAccount.toString(),
keyIdentifier: new KeyIdentifier(
asset.baseAsset.api.getKeyIdentifier({
purpose,
accountIndex: walletAccount.index,
chainIndex,
addressIndex,
compatibilityMode: walletAccount.compatibilityMode,
})
),
}),
purpose,
chainIndex,
addressIndex,
}
})
}

@@ -65,0 +85,0 @@

{
"name": "@exodus/address-provider",
"version": "11.2.0",
"version": "11.3.0",
"description": "Address provider for deriving and tracking used and unused addresses.",

@@ -39,3 +39,3 @@ "author": "Exodus Movement, Inc.",

"@exodus/bip32": "^2.0.0",
"@exodus/key-identifier": "^1.0.0",
"@exodus/key-identifier": "^1.2.1",
"@exodus/key-utils": "^3.3.0",

@@ -78,3 +78,3 @@ "@exodus/models": "^11.13.0",

"@exodus/monero-lib": "^6.4.0",
"@exodus/public-key-provider": "^2.2.2",
"@exodus/public-key-provider": "^2.3.1",
"@exodus/ripple-lib": "^2.9.6",

@@ -90,3 +90,3 @@ "@exodus/solana-lib": "^2.0.0",

},
"gitHead": "6eb57a7122a8f6751a018d6135e9d8088f86d010"
"gitHead": "7dbd2025af2c73ae13960b1fbaa10998c4a69e98"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc