diff --git a/src/constants.ts b/src/constants.ts index 32e57c1..a570fe5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,3 +4,5 @@ export const JRPC_METHODS = { IMPORT_SHARE: "ImportShare", GET_SHARE_OR_KEY_ASSIGN: "GetShareOrKeyAssign", }; + +export const SAPPHIRE_METADATA_URL = "https://node-1.node.web3auth.io/metadata"; diff --git a/src/helpers/metadataUtils.ts b/src/helpers/metadataUtils.ts index 9a9db05..efea217 100644 --- a/src/helpers/metadataUtils.ts +++ b/src/helpers/metadataUtils.ts @@ -5,6 +5,7 @@ import { ec } from "elliptic"; import stringify from "json-stable-stringify"; import log from "loglevel"; +import { SAPPHIRE_METADATA_URL } from "../constants"; import { EciesHex, GetOrSetNonceResult, MetadataParams } from "../interfaces"; import { encParamsHexToBuf } from "./common"; import { keccak256 } from "./keyUtils"; @@ -90,3 +91,13 @@ export async function getNonce( ): Promise { return getOrSetNonce(legacyMetadataHost, ecCurve, serverTimeOffset, X, Y, privKey, true); } + +export async function getOrSetSapphireMetadataNonce(X: string, Y: string): Promise { + const data = { + pub_key_X: X, + pub_key_Y: Y, + key_type: "secp256k1", + set_data: { operation: "getOrSetNonce" }, + }; + return post(`${SAPPHIRE_METADATA_URL}/get_or_set_nonce`, data, undefined, { useAPIKey: true }); +} diff --git a/src/helpers/nodeUtils.ts b/src/helpers/nodeUtils.ts index 9f6e607..32b8cf5 100644 --- a/src/helpers/nodeUtils.ts +++ b/src/helpers/nodeUtils.ts @@ -26,7 +26,7 @@ import { Some } from "../some"; import { calculateMedian, kCombinations, normalizeKeysResult, thresholdSame } from "./common"; import { generateAddressFromPrivKey, generateAddressFromPubKey, keccak256 } from "./keyUtils"; import { lagrangeInterpolation } from "./langrangeInterpolatePoly"; -import { decryptNodeData, getMetadata, getOrSetNonce } from "./metadataUtils"; +import { decryptNodeData, getMetadata, getOrSetNonce, getOrSetSapphireMetadataNonce } from "./metadataUtils"; export const GetPubKeyOrKeyAssign = async (params: { endpoints: string[]; @@ -56,7 +56,7 @@ export const GetPubKeyOrKeyAssign = async (params: { let nonceResult: GetOrSetNonceResult | undefined; const nodeIndexes: number[] = []; - const result = await Some, KeyLookupResult>(lookupPromises, (lookupResults) => { + const result = await Some, KeyLookupResult>(lookupPromises, async (lookupResults) => { const lookupPubKeys = lookupResults.filter((x1) => { if (x1 && !x1.error) { return x1; @@ -88,6 +88,15 @@ export const GetPubKeyOrKeyAssign = async (params: { } } } + + // if nonce result is not returned by nodes, fetch directly from metadata + if (!nonceResult) { + const metadataNonceResult = await getOrSetSapphireMetadataNonce(keyResult.keys[0].pub_key_X, keyResult.keys[0].pub_key_Y); + // rechecking nonceResult to avoid promise race condition. + if (!nonceResult && metadataNonceResult) { + nonceResult = metadataNonceResult; + } + } } const serverTimeOffsets: number[] = []; @@ -369,9 +378,15 @@ export async function retrieveOrImportShare(params: { // if both thresholdNonceData and extended_verifier_id are not available // then we need to throw other wise address would be incorrect. if (!thresholdNonceData && !verifierParams.extended_verifier_id && !LEGACY_NETWORKS_ROUTE_MAP[network as TORUS_LEGACY_NETWORK_TYPE]) { - throw new Error( - `invalid metadata result from nodes, nonce metadata is empty for verifier: ${verifier} and verifierId: ${verifierParams.verifier_id}` - ); + const metadataNonceResult = await getOrSetSapphireMetadataNonce(thresholdPublicKey.X, thresholdPublicKey.Y); + // rechecking nonceResult to avoid promise race condition. + if (metadataNonceResult && !thresholdNonceData) { + thresholdNonceData = metadataNonceResult; + } else { + throw new Error( + `invalid metadata result from nodes, nonce metadata is empty for verifier: ${verifier} and verifierId: ${verifierParams.verifier_id}` + ); + } } const thresholdReqCount = importedShares.length > 0 ? endpoints.length : minThreshold; diff --git a/src/some.ts b/src/some.ts index ca72333..a9995c8 100644 --- a/src/some.ts +++ b/src/some.ts @@ -15,9 +15,9 @@ export class SomeError extends Error { // temp key should not be logged anywhere const message = `Unable to resolve enough promises. errors: ${errors.map((x) => x?.message || x).join(", ")}, + predicate error: ${predicate}, ${responses.length} responses, - responses: ${JSON.stringify(responses)}, - predicate error: ${predicate}`; + responses: ${JSON.stringify(responses)}`; super(message); this.errors = errors; this.responses = responses; diff --git a/test/testnet.test.ts b/test/testnet.test.ts index 719c67e..60f183c 100644 --- a/test/testnet.test.ts +++ b/test/testnet.test.ts @@ -258,7 +258,7 @@ describe("torus utils migrated testnet on sapphire", function () { network: TORUS_LEGACY_NETWORK.TESTNET, clientId: "YOUR_CLIENT_ID", enableOneKey: true, - serverTimeOffset: -100, + serverTimeOffset: -700, }); const { torusNodeSSSEndpoints: torusNodeEndpoints, torusIndexes } = await TORUS_NODE_MANAGER.getNodeDetails(verifierDetails); try {