Normalize Gnosis bridge chain for USDC
Some checks failed
deploy / deploy (push) Failing after 38s

Proof: Gnosis NEAR Intents assets now persist bridge chain eth:100, repo seed corrects legacy USDC chain rows, and tests prove USDC is not inventory-enabled until a pair activation enables it.

Assumptions: NEAR Intents bridge deposit_address uses eth:100 for Gnosis funding handles while dashboard blockchain labels remain gnosis.

Still fake: USDC deposit credit and live solver fills are not proven by this change; supported_tokens RPC remains upstream-unavailable.
This commit is contained in:
philipp 2026-05-13 15:47:23 +02:00
parent 4bf15be22e
commit c94d651fc9
3 changed files with 65 additions and 7 deletions

View file

@ -33,6 +33,7 @@ export function normalizeOneClickToken(token) {
const symbol = stringField(token.symbol, 'symbol');
const decimals = integerField(token.decimals, 'decimals');
const blockchain = stringField(token.blockchain ?? token.chain, 'blockchain');
const chain = normalizeBridgeChain({ assetId, blockchain });
const contractAddress = optionalString(token.contractAddress ?? token.contract_address);
const latestPrice = token.price == null ? null : String(token.price);
const priceUpdatedAt = optionalTimestamp(token.priceUpdatedAt ?? token.price_updated_at);
@ -44,7 +45,7 @@ export function normalizeOneClickToken(token) {
label: symbol,
decimals,
blockchain,
chain: blockchain,
chain,
contractAddress,
latestPrice,
priceUpdatedAt,
@ -130,7 +131,7 @@ export function buildSeedAssets() {
label: 'USDC',
decimals: 6,
blockchain: 'gnosis',
chain: 'gnosis',
chain: 'eth:100',
contractAddress: '0x2a22f9c3b484c3629090feed35f17ff8f88f76f0',
latestPrice: null,
priceUpdatedAt: null,
@ -255,6 +256,15 @@ function optionalString(value) {
return normalized || null;
}
function normalizeBridgeChain({ assetId, blockchain }) {
const normalizedBlockchain = String(blockchain || '').trim();
const normalizedAssetId = String(assetId || '').trim();
if (normalizedBlockchain === 'gnosis' || normalizedAssetId.startsWith('nep141:gnosis-')) {
return 'eth:100';
}
return normalizedBlockchain;
}
function integerField(value, field) {
const number = Number(value);
if (!Number.isInteger(number) || number < 0) {

View file

@ -1564,11 +1564,11 @@ async function upsertSeedAsset(pool, { asset, now }) {
symbol = EXCLUDED.symbol,
label = EXCLUDED.label,
decimals = EXCLUDED.decimals,
blockchain = COALESCE(${TRADING_ASSETS_TABLE}.blockchain, EXCLUDED.blockchain),
chain = COALESCE(${TRADING_ASSETS_TABLE}.chain, EXCLUDED.chain),
blockchain = EXCLUDED.blockchain,
chain = EXCLUDED.chain,
contract_address = COALESCE(${TRADING_ASSETS_TABLE}.contract_address, EXCLUDED.contract_address),
supported = ${TRADING_ASSETS_TABLE}.supported OR EXCLUDED.supported,
enabled_for_inventory = true,
enabled_for_inventory = ${TRADING_ASSETS_TABLE}.enabled_for_inventory OR EXCLUDED.enabled_for_inventory,
role = COALESCE(${TRADING_ASSETS_TABLE}.role, EXCLUDED.role),
withdraw_address = COALESCE(NULLIF(${TRADING_ASSETS_TABLE}.withdraw_address, ''), EXCLUDED.withdraw_address),
raw_payload = CASE
@ -1766,7 +1766,7 @@ async function upsertImportedAsset(pool, { asset, fetchedAt }) {
label = EXCLUDED.label,
decimals = EXCLUDED.decimals,
blockchain = EXCLUDED.blockchain,
chain = COALESCE(${TRADING_ASSETS_TABLE}.chain, EXCLUDED.chain),
chain = EXCLUDED.chain,
contract_address = EXCLUDED.contract_address,
latest_price = EXCLUDED.latest_price,
price_updated_at = EXCLUDED.price_updated_at,

View file

@ -38,6 +38,21 @@ test('1Click token normalizer preserves live asset fields', () => {
assert.equal(token.priceUpdatedAt, '2026-05-12T16:25:00.425Z');
});
test('1Click token normalizer maps Gnosis assets to bridge chain id', () => {
const token = normalizeOneClickToken({
assetId: CURRENT_USDC_ASSET_ID,
decimals: 6,
blockchain: 'gnosis',
symbol: 'USDC',
price: 1,
priceUpdatedAt: '2026-05-12T16:25:00.425Z',
contractAddress: '0x2a22f9c3b484c3629090feed35f17ff8f88f76f0',
});
assert.equal(token.blockchain, 'gnosis');
assert.equal(token.chain, 'eth:100');
});
test('supported token import is idempotent, does not enable inventory, and retires missing assets', async () => {
const pool = createMemoryPool();
const first = await importSupportedAssets(pool, {
@ -106,9 +121,42 @@ test('seeded DB config preserves current nBTC/EURe pair, 49 bps edge, and legacy
assert.equal(snapshot.pairs.length, 2);
assert.equal(snapshot.pairByKey.get(snapshot.activePair).strategyConfig.edgeBps, 49);
assert.equal(snapshot.trackedAssetIds.includes(LEGACY_OMFT_BTC_ASSET_ID), true);
assert.equal(snapshot.assetRegistry.get(CURRENT_USDC_ASSET_ID).chain, 'eth:100');
assert.equal(snapshot.trackedAssetIds.includes(CURRENT_USDC_ASSET_ID), false);
assert.equal([...snapshot.makerPairKeys].some((pair) => pair.includes(LEGACY_OMFT_BTC_ASSET_ID)), false);
});
test('repo seed corrects legacy USDC Gnosis chain without inventory-enabling it', async () => {
const pool = createMemoryPool();
pool.assets.set(CURRENT_USDC_ASSET_ID, {
asset_id: CURRENT_USDC_ASSET_ID,
venue: 'near-intents',
symbol: 'USDC',
label: 'USDC',
decimals: 6,
blockchain: 'gnosis',
chain: 'gnosis',
contract_address: '0x2a22f9c3b484c3629090feed35f17ff8f88f76f0',
latest_price: '1',
price_updated_at: '2026-05-12T16:25:00.425Z',
supported: true,
retired_at: null,
enabled_for_inventory: false,
role: null,
withdraw_address: '',
raw_payload: { source: 'legacy_test_row' },
last_supported_at: '2026-05-12T16:25:00.425Z',
updated_at: '2026-05-12T16:25:00.425Z',
});
await seedTradingConfig(pool, { now: '2026-05-12T16:35:00.000Z' });
const snapshot = await loadTradingConfig(pool);
const usdc = snapshot.assetRegistry.get(CURRENT_USDC_ASSET_ID);
assert.equal(usdc.chain, 'eth:100');
assert.equal(usdc.enabledForInventory, false);
});
test('missing DB pair config fails closed', async () => {
const snapshot = await loadTradingConfig(createMemoryPool());
@ -536,7 +584,7 @@ function insertAsset(pool, params) {
price_updated_at: priceUpdatedAt,
supported: seed ? (previous?.supported || params[10]) : true,
retired_at: null,
enabled_for_inventory: seed ? true : previous?.enabled_for_inventory === true,
enabled_for_inventory: seed ? previous?.enabled_for_inventory === true || params[11] === true : previous?.enabled_for_inventory === true,
role: seed ? params[12] : previous?.role || null,
withdraw_address: seed ? params[13] : previous?.withdraw_address || '',
raw_payload: JSON.parse(seed ? params[14] : params[10]),