From f699600c5ac72c4d28f13c58018239e520757fbc Mon Sep 17 00:00:00 2001 From: DenisIvanov26 Date: Mon, 15 Apr 2024 14:16:36 -0500 Subject: [PATCH] remove ccip and ens --- src.ts/_tests/test-address.ts | 3 +- src.ts/address/address.ts | 87 ---- src.ts/address/checks.ts | 12 +- src.ts/address/index.ts | 16 +- src.ts/contract/contract.ts | 53 +-- src.ts/hash/typed-data.ts | 56 +-- src.ts/providers/abstract-provider.ts | 135 +----- src.ts/providers/abstract-signer.ts | 11 +- src.ts/providers/contracts.ts | 5 - src.ts/providers/ens-resolver.ts | 606 -------------------------- src.ts/providers/index.ts | 5 - src.ts/providers/provider-jsonrpc.ts | 17 +- src.ts/providers/provider.ts | 23 +- src.ts/providers/signer.ts | 10 +- src.ts/quais.ts | 11 +- src.ts/utils/errors.ts | 32 -- src.ts/utils/index.ts | 4 +- src.ts/wallet/base-wallet.ts | 27 +- 18 files changed, 41 insertions(+), 1072 deletions(-) delete mode 100644 src.ts/providers/ens-resolver.ts diff --git a/src.ts/_tests/test-address.ts b/src.ts/_tests/test-address.ts index 49f5e577..a98b8781 100644 --- a/src.ts/_tests/test-address.ts +++ b/src.ts/_tests/test-address.ts @@ -9,7 +9,7 @@ import type { } from "./types.js"; import { - getAddress, getIcapAddress, + getAddress, getCreateAddress, getCreate2Address } from "../index.js"; @@ -76,7 +76,6 @@ describe("computes ICAP address", function() { const tests = loadTests("accounts"); for (const test of tests) { it(`computes the ICAP address: ${ test.name }`, function() { - assert.equal(getIcapAddress(test.address), test.icap); assert.equal(getAddress(test.address.toLowerCase()), test.address); assert.equal(getAddress("0x" + test.address.substring(2).toUpperCase()), test.address); }); diff --git a/src.ts/address/address.ts b/src.ts/address/address.ts index 96c1751c..c73be5aa 100644 --- a/src.ts/address/address.ts +++ b/src.ts/address/address.ts @@ -1,10 +1,6 @@ import { keccak256 } from "../crypto/index.js"; import { getBytes, assertArgument, BytesLike, concat, zeroPadValue, dataSlice, BigNumberish, toBigInt, toBeHex, stripZerosLeft } from "../utils/index.js"; - -const BN_0 = BigInt(0); -const BN_36 = BigInt(36); - function getChecksumAddress(address: string): string { // if (!isHexString(address, 20)) { // logger.throwArgumentError("invalid address", "address", address); @@ -33,54 +29,6 @@ function getChecksumAddress(address: string): string { return "0x" + chars.join(""); } -// See: https://en.wikipedia.org/wiki/International_Bank_Account_Number - -// Create lookup table -const ibanLookup: { [character: string]: string } = { }; -for (let i = 0; i < 10; i++) { ibanLookup[String(i)] = String(i); } -for (let i = 0; i < 26; i++) { ibanLookup[String.fromCharCode(65 + i)] = String(10 + i); } - -// How many decimal digits can we process? (for 64-bit float, this is 15) -// i.e. Math.floor(Math.log10(Number.MAX_SAFE_INTEGER)); -const safeDigits = 15; - -function ibanChecksum(address: string): string { - address = address.toUpperCase(); - address = address.substring(4) + address.substring(0, 2) + "00"; - - let expanded = address.split("").map((c) => { return ibanLookup[c]; }).join(""); - - // Javascript can handle integers safely up to 15 (decimal) digits - while (expanded.length >= safeDigits){ - let block = expanded.substring(0, safeDigits); - expanded = parseInt(block, 10) % 97 + expanded.substring(block.length); - } - - let checksum = String(98 - (parseInt(expanded, 10) % 97)); - while (checksum.length < 2) { checksum = "0" + checksum; } - - return checksum; -}; - -const Base36 = (function() {; - const result: Record = { }; - for (let i = 0; i < 36; i++) { - const key = "0123456789abcdefghijklmnopqrstuvwxyz"[i]; - result[key] = BigInt(i); - } - return result; -})(); - -function fromBase36(value: string): bigint { - value = value.toLowerCase(); - - let result = BN_0; - for (let i = 0; i < value.length; i++) { - result = result * BN_36 + Base36[value[i]]; - } - return result; -} - /** * Returns a normalized and checksumed address for %%address%%. * This accepts non-checksum addresses, checksum addresses and @@ -134,44 +82,9 @@ export function getAddress(address: string): string { return result; } - // Maybe ICAP? (we only support direct mode) - if (address.match(/^XE[0-9]{2}[0-9A-Za-z]{30,31}$/)) { - // It is an ICAP address with a bad checksum - assertArgument(address.substring(2, 4) === ibanChecksum(address), "bad icap checksum", "address", address); - - let result = fromBase36(address.substring(4)).toString(16); - while (result.length < 40) { result = "0" + result; } - return getChecksumAddress("0x" + result); - } - assertArgument(false, "invalid address", "address", address); } -/** - * The [ICAP Address format](link-icap) format is an early checksum - * format which attempts to be compatible with the banking - * industry [IBAN format](link-wiki-iban) for bank accounts. - * - * It is no longer common or a recommended format. - * - * @example: - * getIcapAddress("0x8ba1f109551bd432803012645ac136ddd64dba72"); - * //_result: - * - * getIcapAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK36"); - * //_result: - * - * // Throws an error if the ICAP checksum is wrong - * getIcapAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK37"); - * //_error: - */ -export function getIcapAddress(address: string): string { - //let base36 = _base16To36(getAddress(address).substring(2)).toUpperCase(); - let base36 = BigInt(getAddress(address)).toString(36).toUpperCase(); - while (base36.length < 30) { base36 = "0" + base36; } - return "XE" + ibanChecksum("XE00" + base36) + base36; -} - export function getContractAddress(from: string, nonce: BigNumberish, data: BytesLike): string { const nonceBytes = zeroPadValue(toBeHex(toBigInt(nonce)), 8); return getAddress(dataSlice(keccak256(concat([getAddress(from), nonceBytes, stripZerosLeft(data) ])), 12)) diff --git a/src.ts/address/checks.ts b/src.ts/address/checks.ts index 675679a7..e299119a 100644 --- a/src.ts/address/checks.ts +++ b/src.ts/address/checks.ts @@ -1,8 +1,8 @@ -import { assert, assertArgument } from "../utils/index.js"; +import { assertArgument } from "../utils/index.js"; import { getAddress } from "./address.js"; -import type { Addressable, AddressLike, NameResolver } from "./index.js"; +import type { Addressable, AddressLike } from "./index.js"; /** @@ -59,7 +59,6 @@ export function isAddress(value: any): value is string { async function checkAddress(target: any, promise: Promise): Promise { const result = await promise; if (result == null || result === "0x0000000000000000000000000000000000000000") { - assert(typeof(target) !== "string", "unconfigured name", "UNCONFIGURED_NAME", { value: target }); assertArgument(false, "invalid AddressLike value; did not resolve to a value address", "target", target); } return getAddress(result); @@ -102,16 +101,11 @@ async function checkAddress(target: any, promise: Promise): Promi * resolveAddress("nothing-here.ricmoo.eth") * //_error: */ -export function resolveAddress(target: AddressLike, resolver?: null | NameResolver): string | Promise { +export function resolveAddress(target: AddressLike): string | Promise { if (typeof(target) === "string") { if (target.match(/^0x[0-9a-f]{40}$/i)) { return getAddress(target); } - assert(resolver != null, "ENS resolution requires a provider", - "UNSUPPORTED_OPERATION", { operation: "resolveName" }); - - return checkAddress(target, resolver.resolveName(target)); - } else if (isAddressable(target)) { return checkAddress(target, target.getAddress()); diff --git a/src.ts/address/index.ts b/src.ts/address/index.ts index 1bf31b22..22cdeaf5 100644 --- a/src.ts/address/index.ts +++ b/src.ts/address/index.ts @@ -35,21 +35,7 @@ export interface Addressable { */ export type AddressLike = string | Promise | Addressable; -/** - * An interface for any object which can resolve an ENS name. - */ -export interface NameResolver { - /** - * Resolve to the address for the ENS %%name%%. - * - * Resolves to ``null`` if the name is unconfigued. Use - * [[resolveAddress]] (passing this object as %%resolver%%) to - * throw for names that are unconfigured. - */ - resolveName(name: string): Promise; -} - -export { getAddress, getIcapAddress } from "./address.js"; +export { getAddress } from "./address.js"; export { getCreateAddress, getCreate2Address } from "./contract-address.js"; diff --git a/src.ts/contract/contract.ts b/src.ts/contract/contract.ts index e19b6b11..cb195758 100644 --- a/src.ts/contract/contract.ts +++ b/src.ts/contract/contract.ts @@ -5,7 +5,7 @@ import { isAddressable, resolveAddress } from "../address/index.js"; import { copyRequest, Log, TransactionResponse } from "../providers/provider.js"; import { defineProperties, getBigInt, isCallException, isHexString, resolveProperties, - isError, makeError, assert, assertArgument + isError, assert, assertArgument } from "../utils/index.js"; import { @@ -15,7 +15,7 @@ import { } from "./wrappers.js"; import type { EventFragment, FunctionFragment, InterfaceAbi, ParamType, Result } from "../abi/index.js"; -import type { Addressable, NameResolver } from "../address/index.js"; +import type { Addressable } from "../address/index.js"; import type { EventEmitterable, Listener } from "../utils/index.js"; import type { BlockTag, ContractRunner, Provider, TransactionRequest, TopicFilter @@ -48,10 +48,6 @@ interface ContractRunnerSender extends ContractRunner { sendTransaction: (tx: TransactionRequest) => Promise; } -interface ContractRunnerResolver extends ContractRunner { - resolveName: (name: string | Addressable) => Promise; -} - function canCall(value: any): value is ContractRunnerCaller { return (value && typeof(value.call) === "function"); } @@ -60,22 +56,10 @@ function canEstimate(value: any): value is ContractRunnerEstimater { return (value && typeof(value.estimateGas) === "function"); } -function canResolve(value: any): value is ContractRunnerResolver { - return (value && typeof(value.resolveName) === "function"); -} - function canSend(value: any): value is ContractRunnerSender { return (value && typeof(value.sendTransaction) === "function"); } -function getResolver(value: any): undefined | NameResolver { - if (value != null) { - if (canResolve(value)) { return value; } - if (value.provider) { return value.provider; } - } - return undefined; -} - class PreparedTopicFilter implements DeferredTopicFilter { #filter: Promise; readonly fragment!: EventFragment; @@ -86,9 +70,6 @@ class PreparedTopicFilter implements DeferredTopicFilter { throw new Error("too many arguments"); } - // Recursively descend into args and resolve any addresses - const runner = getRunner(contract.runner, "resolveName"); - const resolver = canResolve(runner) ? runner: null; this.#filter = (async function() { const resolvedArgs = await Promise.all(fragment.inputs.map((param, index) => { const arg = args[index]; @@ -97,9 +78,9 @@ class PreparedTopicFilter implements DeferredTopicFilter { return param.walkAsync(args[index], (type, value) => { if (type === "address") { if (Array.isArray(value)) { - return Promise.all(value.map((v) => resolveAddress(v, resolver))); + return Promise.all(value.map((v) => resolveAddress(v))); } - return resolveAddress(value, resolver); + return resolveAddress(value); } return value; }); @@ -164,12 +145,10 @@ export async function copyOverrides(arg: any, */ export async function resolveArgs(_runner: null | ContractRunner, inputs: ReadonlyArray, args: Array): Promise> { // Recursively descend into args and resolve any addresses - const runner = getRunner(_runner, "resolveName"); - const resolver = canResolve(runner) ? runner: null; return await Promise.all(inputs.map((param, index) => { return param.walkAsync(args[index], (type, value) => { value = Typed.dereference(value, type); - if (type === "address") { return resolveAddress(value, resolver); } + if (type === "address") { return resolveAddress(value); } return value; }); })); @@ -184,7 +163,7 @@ function buildWrappedFallback(contract: BaseContract): WrappedFallback { tx.to = await contract.getAddress(); if (tx.from) { - tx.from = await resolveAddress(tx.from, getResolver(contract.runner)); + tx.from = await resolveAddress(tx.from); } const iface = contract.interface; @@ -715,28 +694,8 @@ export class BaseContract implements Addressable, EventEmitterable { - if (addr == null) { - throw makeError("an ENS name used for a contract target must be correctly configured", "UNCONFIGURED_NAME", { - value: target - }); - } - getInternal(this).addr = addr; - return addr; - }); - } } else { addrPromise = target.getAddress().then((addr) => { if (addr == null) { throw new Error("TODO"); } diff --git a/src.ts/hash/typed-data.ts b/src.ts/hash/typed-data.ts index 4d9ce1ac..7b5bec36 100644 --- a/src.ts/hash/typed-data.ts +++ b/src.ts/hash/typed-data.ts @@ -3,7 +3,7 @@ import { getAddress } from "../address/index.js"; import { keccak256 } from "../crypto/index.js"; import { recoverAddress } from "../transaction/index.js"; import { - concat, defineProperties, getBigInt, getBytes, hexlify, isHexString, mask, toBeHex, toQuantity, toTwos, zeroPadValue, + concat, defineProperties, getBigInt, getBytes, hexlify, mask, toBeHex, toQuantity, toTwos, zeroPadValue, assertArgument } from "../utils/index.js"; @@ -492,60 +492,6 @@ export class TypedDataEncoder { return keccak256(TypedDataEncoder.encode(domain, types, value)); } - // Replaces all address types with ENS names with their looked up address - /** - * Resolves to the value from resolving all addresses in %%value%% for - * %%types%% and the %%domain%%. - */ - static async resolveNames(domain: TypedDataDomain, types: Record>, value: Record, resolveName: (name: string) => Promise): Promise<{ domain: TypedDataDomain, value: any }> { - // Make a copy to isolate it from the object passed in - domain = Object.assign({ }, domain); - - // Allow passing null to ignore value - for (const key in domain) { - if ((>domain)[key] == null) { - delete (>domain)[key]; - } - } - - // Look up all ENS names - const ensCache: Record = { }; - - // Do we need to look up the domain's verifyingContract? - if (domain.verifyingContract && !isHexString(domain.verifyingContract, 20)) { - ensCache[domain.verifyingContract] = "0x"; - } - - // We are going to use the encoder to visit all the base values - const encoder = TypedDataEncoder.from(types); - - // Get a list of all the addresses - encoder.visit(value, (type: string, value: any) => { - if (type === "address" && !isHexString(value, 20)) { - ensCache[value] = "0x"; - } - return value; - }); - - // Lookup each name - for (const name in ensCache) { - ensCache[name] = await resolveName(name); - } - - // Replace the domain verifyingContract if needed - if (domain.verifyingContract && ensCache[domain.verifyingContract]) { - domain.verifyingContract = ensCache[domain.verifyingContract]; - } - - // Replace all ENS names with their address - value = encoder.visit(value, (type: string, value: any) => { - if (type === "address" && ensCache[value]) { return ensCache[value]; } - return value; - }); - - return { domain, value }; - } - /** * Returns the JSON-encoded payload expected by nodes which implement * the JSON-RPC [[link-eip-712]] method. diff --git a/src.ts/providers/abstract-provider.ts b/src.ts/providers/abstract-provider.ts index 9bbf9db0..e32b227f 100644 --- a/src.ts/providers/abstract-provider.ts +++ b/src.ts/providers/abstract-provider.ts @@ -14,21 +14,18 @@ // migrate the listener to the static event. We also need to maintain a map // of Signer/ENS name to address so we can sync respond to listenerCount. -import { getAddress, resolveAddress } from "../address/index.js"; -import { ShardData, ZeroAddress } from "../constants/index.js"; -import { Contract } from "../contract/index.js"; -import { namehash } from "../hash/index.js"; +import { resolveAddress } from "../address/index.js"; +import { ShardData } from "../constants/index.js"; import { Transaction } from "../transaction/index.js"; import { hexlify, isHexString, getBigInt, getNumber, - isError, makeError, assert, assertArgument, + makeError, assert, assertArgument, FetchRequest, toQuantity, defineProperties, EventPayload, resolveProperties, } from "../utils/index.js"; -import { EnsResolver } from "./ens-resolver.js"; import { formatBlock, formatLog, formatTransactionReceipt, formatTransactionResponse } from "./format.js"; @@ -59,8 +56,6 @@ type Timer = ReturnType; // Constants const BN_2 = BigInt(2); -const MAX_CCIP_REDIRECTS = 10; - function isPromise(value: any): value is Promise { return (value && typeof(value.then) === "function"); } @@ -276,7 +271,7 @@ async function getSubscription(_event: ProviderEvent, provider: AbstractProvider addresses.push(addr); } else { promises.push((async () => { - addresses.push(await resolveAddress(addr, provider)); + addresses.push(await resolveAddress(addr)); })()); } } @@ -693,64 +688,6 @@ export class AbstractProvider implements Provider { return await perform; } - /** - * Resolves to the data for executing the CCIP-read operations. - */ - async ccipReadFetch(tx: PerformActionTransaction, calldata: string, urls: Array): Promise { - if (this.disableCcipRead || urls.length === 0 || tx.to == null) { return null; } - - const sender = tx.to.toLowerCase(); - const data = calldata.toLowerCase(); - - const errorMessages: Array = [ ]; - - for (let i = 0; i < urls.length; i++) { - const url = urls[i]; - - // URL expansion - const href = url.replace("{sender}", sender).replace("{data}", data); - - // If no {data} is present, use POST; otherwise GET - //const json: string | null = (url.indexOf("{data}") >= 0) ? null: JSON.stringify({ data, sender }); - - //const result = await fetchJson({ url: href, errorPassThrough: true }, json, (value, response) => { - // value.status = response.statusCode; - // return value; - //}); - const request = new FetchRequest(href); - if (url.indexOf("{data}") === -1) { - request.body = { data, sender }; - } - - this.emit("debug", { action: "sendCcipReadFetchRequest", request, index: i, urls }); - - let errorMessage = "unknown error"; - - const resp = await request.send(); - try { - const result = resp.bodyJson; - if (result.data) { - this.emit("debug", { action: "receiveCcipReadFetchResult", request, result }); - return result.data; - } - if (result.message) { errorMessage = result.message; } - this.emit("debug", { action: "receiveCcipReadFetchError", request, result }); - } catch (error) { } - - // 4xx indicates the result is not present; stop - assert(resp.statusCode < 400 || resp.statusCode >= 500, `response not found during CCIP fetch: ${ errorMessage }`, - "OFFCHAIN_FAULT", { reason: "404_MISSING_RESOURCE", transaction: tx, info: { url, errorMessage } }); - - // 5xx indicates server issue; try the next url - errorMessages.push(errorMessage); - } - - assert(false, `error encountered during CCIP fetch: ${ errorMessages.map((m) => JSON.stringify(m)).join(", ") }`, "OFFCHAIN_FAULT", { - reason: "500_SERVER_ERROR", - transaction: tx, info: { urls, errorMessages } - }); - } - /** * Provides the opportunity for a sub-class to wrap a block before * returning it, to add additional properties or an alternate @@ -826,7 +763,7 @@ export class AbstractProvider implements Provider { * address. */ _getAddress(address: AddressLike): string | Promise { - return resolveAddress(address, this); + return resolveAddress(address); } /** @@ -954,7 +891,7 @@ export class AbstractProvider implements Provider { [ "to", "from" ].forEach((key) => { if ((request)[key] == null) { return; } - const addr = resolveAddress((request)[key], this); + const addr = resolveAddress((request)[key]); if (isPromise(addr)) { promises.push((async function() { (request)[key] = await addr; })()); } else { @@ -1096,10 +1033,6 @@ export class AbstractProvider implements Provider { } async #call(tx: PerformActionTransaction, blockTag: string, attempt: number): Promise { - assert (attempt < MAX_CCIP_REDIRECTS, "CCIP read exceeded maximum redirections", "OFFCHAIN_FAULT", { - reason: "TOO_MANY_REDIRECTS", - transaction: Object.assign({ }, tx, { blockTag, enableCcipRead: true }) - }); // This came in as a PerformActionTransaction, so to/from are safe; we can cast const transaction = copyRequest(tx); @@ -1328,62 +1261,6 @@ export class AbstractProvider implements Provider { }); } - async getResolver(name: string): Promise { - return await EnsResolver.fromName(this, name); - } - - async getAvatar(name: string): Promise { - const resolver = await this.getResolver(name); - if (resolver) { return await resolver.getAvatar(); } - return null; - } - - async resolveName(name: string): Promise{ - const resolver = await this.getResolver(name); - if (resolver) { return await resolver.getAddress(); } - return null; - } - - async lookupAddress(address: string): Promise { - address = getAddress(address); - const node = namehash(address.substring(2).toLowerCase() + ".addr.reverse"); - - try { - - const ensAddr = await EnsResolver.getEnsAddress(this); - const ensContract = new Contract(ensAddr, [ - "function resolver(bytes32) view returns (address)" - ], this); - - const resolver = await ensContract.resolver(node); - if (resolver == null || resolver === ZeroAddress) { return null; } - - const resolverContract = new Contract(resolver, [ - "function name(bytes32) view returns (string)" - ], this); - const name = await resolverContract.name(node); - - // Failed forward resolution - const check = await this.resolveName(name); - if (check !== address) { return null; } - - return name; - - } catch (error) { - // No data was returned from the resolver - if (isError(error, "BAD_DATA") && error.value === "0x") { - return null; - } - - // Something reerted - if (isError(error, "CALL_EXCEPTION")) { return null; } - - throw error; - } - - return null; - } - async waitForTransaction(hash: string, _confirms?: null | number, timeout?: null | number): Promise { const shard = this.shardFromHash(hash); const confirms = (_confirms != null) ? _confirms: 1; diff --git a/src.ts/providers/abstract-signer.ts b/src.ts/providers/abstract-signer.ts index d8425948..2c045049 100644 --- a/src.ts/providers/abstract-signer.ts +++ b/src.ts/providers/abstract-signer.ts @@ -30,13 +30,13 @@ function checkProvider(signer: AbstractSigner, operation: string): Provider { async function populate(signer: AbstractSigner, tx: TransactionRequest): Promise> { let pop: any = copyRequest(tx); - if (pop.to != null) { pop.to = resolveAddress(pop.to, signer); } + if (pop.to != null) { pop.to = resolveAddress(pop.to); } if (pop.from != null) { const from = pop.from; pop.from = Promise.all([ signer.getAddress(), - resolveAddress(from, signer) + resolveAddress(from) ]).then(([ address, from ]) => { assertArgument(address.toLowerCase() === from.toLowerCase(), "transaction from mismatch", "tx.from", from); @@ -76,7 +76,7 @@ export abstract class AbstractSigner

{ - return resolveAddress(address, this); + return resolveAddress(address); } async shardFromAddress(_address: AddressLike): Promise { @@ -175,11 +175,6 @@ export abstract class AbstractSigner

{ - const provider = checkProvider(this, "resolveName"); - return await provider.resolveName(name); - } - async sendTransaction(tx: TransactionRequest): Promise { const provider = checkProvider(this, "sendTransaction"); let sender = await this.getAddress() diff --git a/src.ts/providers/contracts.ts b/src.ts/providers/contracts.ts index abb6d2b8..57ca77b4 100644 --- a/src.ts/providers/contracts.ts +++ b/src.ts/providers/contracts.ts @@ -30,11 +30,6 @@ export interface ContractRunner { */ call?: (tx: TransactionRequest) => Promise; - /** - * Required to support ENS names - */ - resolveName?: (name: string) => Promise; - /** * Required for state mutating calls */ diff --git a/src.ts/providers/ens-resolver.ts b/src.ts/providers/ens-resolver.ts deleted file mode 100644 index bca3b630..00000000 --- a/src.ts/providers/ens-resolver.ts +++ /dev/null @@ -1,606 +0,0 @@ -/** - * ENS is a service which allows easy-to-remember names to map to - * network addresses. - * - * @_section: api/providers/ens-resolver:ENS Resolver [about-ens-rsolver] - */ - -import { getAddress } from "../address/index.js"; -import { ZeroAddress } from "../constants/index.js"; -import { Contract } from "../contract/index.js"; -import { dnsEncode, namehash } from "../hash/index.js"; -import { - hexlify, isHexString, toBeHex, - defineProperties, encodeBase58, - assert, assertArgument, isError, - FetchRequest -} from "../utils/index.js"; - -import type { FunctionFragment } from "../abi/index.js"; - -import type { BytesLike } from "../utils/index.js"; - -import type { AbstractProvider, AbstractProviderPlugin } from "./abstract-provider.js"; -import type { EnsPlugin } from "./plugins-network.js"; -import type { Provider } from "./provider.js"; - -// @TODO: This should use the fetch-data:ipfs gateway -// Trim off the ipfs:// prefix and return the default gateway URL -function getIpfsLink(link: string): string { - if (link.match(/^ipfs:\/\/ipfs\//i)) { - link = link.substring(12); - } else if (link.match(/^ipfs:\/\//i)) { - link = link.substring(7); - } else { - assertArgument(false, "unsupported IPFS format", "link", link); - } - - return `https:/\/gateway.ipfs.io/ipfs/${ link }`; -} - -/** - * The type of data found during a steip during avatar resolution. - */ -export type AvatarLinkageType = "name" | "avatar" | "!avatar" | "url" | "data" | "ipfs" | - "erc721" | "erc1155" | "!erc721-caip" | "!erc1155-caip" | - "!owner" | "owner" | "!balance" | "balance" | - "metadata-url-base" | "metadata-url-expanded" | "metadata-url" | "!metadata-url" | - "!metadata" | "metadata" | - "!imageUrl" | "imageUrl-ipfs" | "imageUrl" | "!imageUrl-ipfs"; - -/** - * An individual record for each step during avatar resolution. - */ -export interface AvatarLinkage { - /** - * The type of linkage. - */ - type: AvatarLinkageType; - - /** - * The linkage value. - */ - value: string; -}; - -/** - * When resolving an avatar for an ENS name, there are many - * steps involved, fetching metadata, validating results, et cetera. - * - * Some applications may wish to analyse this data, or use this data - * to diagnose promblems, so an **AvatarResult** provides details of - * each completed step during avatar resolution. - */ -export interface AvatarResult { - /** - * How the [[url]] was arrived at, resolving the many steps required - * for an avatar URL. - */ - linkage: Array; - - /** - * The avatar URL or null if the avatar was not set, or there was - * an issue during validation (such as the address not owning the - * avatar or a metadata error). - */ - url: null | string; -}; - -/** - * A provider plugin super-class for processing multicoin address types. - */ -export abstract class MulticoinProviderPlugin implements AbstractProviderPlugin { - /** - * The name. - */ - readonly name!: string; - - /** - * Creates a new **MulticoinProviderPluing** for %%name%%. - */ - constructor(name: string) { - defineProperties(this, { name }); - } - - connect(proivder: Provider): MulticoinProviderPlugin { - return this; - } - - /** - * Returns ``true`` if %%coinType%% is supported by this plugin. - */ - supportsCoinType(coinType: number): boolean { - return false; - } - - /** - * Resovles to the encoded %%address%% for %%coinType%%. - */ - async encodeAddress(coinType: number, address: string): Promise { - throw new Error("unsupported coin"); - } - - /** - * Resovles to the decoded %%data%% for %%coinType%%. - */ - async decodeAddress(coinType: number, data: BytesLike): Promise { - throw new Error("unsupported coin"); - } -} - -const BasicMulticoinPluginId = "org.quais.plugins.provider.BasicMulticoin"; - -/** - * A **BasicMulticoinProviderPlugin** provides service for common - * coin types, which do not require additional libraries to encode or - * decode. - */ -export class BasicMulticoinProviderPlugin extends MulticoinProviderPlugin { - /** - * Creates a new **BasicMulticoinProviderPlugin**. - */ - constructor() { - super(BasicMulticoinPluginId); - } -} - -const matcherIpfs = new RegExp("^(ipfs):/\/(.*)$", "i"); -const matchers = [ - new RegExp("^(https):/\/(.*)$", "i"), - new RegExp("^(data):(.*)$", "i"), - matcherIpfs, - new RegExp("^eip155:[0-9]+/(erc[0-9]+):(.*)$", "i"), -]; - -/** - * A connected object to a resolved ENS name resolver, which can be - * used to query additional details. - */ -export class EnsResolver { - /** - * The connected provider. - */ - provider!: AbstractProvider; - - /** - * The address of the resolver. - */ - address!: string; - - /** - * The name this resolver was resolved against. - */ - name!: string; - - // For EIP-2544 names, the ancestor that provided the resolver - #supports2544: null | Promise; - - #resolver: Contract; - - constructor(provider: AbstractProvider, address: string, name: string) { - defineProperties(this, { provider, address, name }); - this.#supports2544 = null; - - this.#resolver = new Contract(address, [ - "function supportsInterface(bytes4) view returns (bool)", - "function resolve(bytes, bytes) view returns (bytes)", - "function addr(bytes32) view returns (address)", - "function addr(bytes32, uint) view returns (bytes)", - "function text(bytes32, string) view returns (string)", - "function contenthash(bytes32) view returns (bytes)", - ], provider); - - } - - /** - * Resolves to true if the resolver supports wildcard resolution. - */ - async supportsWildcard(): Promise { - if (this.#supports2544 == null) { - this.#supports2544 = (async () => { - try { - return await this.#resolver.supportsInterface("0x9061b923"); - } catch (error) { - // Wildcard resolvers must understand supportsInterface - // and return true. - if (isError(error, "CALL_EXCEPTION")) { return false; } - - // Let future attempts try again... - this.#supports2544 = null; - - throw error; - } - })(); - } - - return await this.#supports2544; - } - - async #fetch(funcName: string, params?: Array): Promise { - params = (params || []).slice(); - const iface = this.#resolver.interface; - - // The first parameters is always the nodehash - params.unshift(namehash(this.name)) - - let fragment: null | FunctionFragment = null; - if (await this.supportsWildcard()) { - fragment = iface.getFunction(funcName); - assert(fragment, "missing fragment", "UNKNOWN_ERROR", { - info: { funcName } - }); - - params = [ - dnsEncode(this.name), - iface.encodeFunctionData(fragment, params) - ]; - - funcName = "resolve(bytes,bytes)"; - } - - params.push({ - enableCcipRead: true - }); - - try { - const result = await this.#resolver[funcName](...params); - - if (fragment) { - return iface.decodeFunctionResult(fragment, result)[0]; - } - - return result; - } catch (error: any) { - if (!isError(error, "CALL_EXCEPTION")) { throw error; } - } - - return null; - } - - /** - * Resolves to the address for %%coinType%% or null if the - * provided %%coinType%% has not been configured. - */ - async getAddress(coinType?: number): Promise { - if (coinType == null) { coinType = 60; } - if (coinType === 60) { - try { - const result = await this.#fetch("addr(bytes32)"); - - // No address - if (result == null || result === ZeroAddress) { return null; } - - return result; - } catch (error: any) { - if (isError(error, "CALL_EXCEPTION")) { return null; } - throw error; - } - } - - // Try decoding its EVM canonical chain as an EVM chain address first - if (coinType >= 0 && coinType < 0x80000000) { - let ethCoinType = coinType + 0x80000000; - - const data = await this.#fetch("addr(bytes32,uint)", [ ethCoinType ]); - if (isHexString(data, 20)) { return getAddress(data); } - } - - let coinPlugin: null | MulticoinProviderPlugin = null; - for (const plugin of this.provider.plugins) { - if (!(plugin instanceof MulticoinProviderPlugin)) { continue; } - if (plugin.supportsCoinType(coinType)) { - coinPlugin = plugin; - break; - } - } - - if (coinPlugin == null) { return null; } - - // keccak256("addr(bytes32,uint256") - const data = await this.#fetch("addr(bytes32,uint)", [ coinType ]); - - // No address - if (data == null || data === "0x") { return null; } - - // Compute the address - const address = await coinPlugin.decodeAddress(coinType, data); - - if (address != null) { return address; } - - assert(false, `invalid coin data`, "UNSUPPORTED_OPERATION", { - operation: `getAddress(${ coinType })`, - info: { coinType, data } - }); - } - - /** - * Resolves to the EIP-634 text record for %%key%%, or ``null`` - * if unconfigured. - */ - async getText(key: string): Promise { - const data = await this.#fetch("text(bytes32,string)", [ key ]); - if (data == null || data === "0x") { return null; } - return data; - } - - /** - * Rsolves to the content-hash or ``null`` if unconfigured. - */ - async getContentHash(): Promise { - // keccak256("contenthash()") - const data = await this.#fetch("contenthash(bytes32)"); - - // No contenthash - if (data == null || data === "0x") { return null; } - - // IPFS (CID: 1, Type: 70=DAG-PB, 72=libp2p-key) - const ipfs = data.match(/^0x(e3010170|e5010172)(([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f]*))$/); - if (ipfs) { - const scheme = (ipfs[1] === "e3010170") ? "ipfs": "ipns"; - const length = parseInt(ipfs[4], 16); - if (ipfs[5].length === length * 2) { - return `${ scheme }:/\/${ encodeBase58("0x" + ipfs[2])}`; - } - } - - // Swarm (CID: 1, Type: swarm-manifest; hash/length hard-coded to keccak256/32) - const swarm = data.match(/^0xe40101fa011b20([0-9a-f]*)$/) - if (swarm && swarm[1].length === 64) { - return `bzz:/\/${ swarm[1] }`; - } - - assert(false, `invalid or unsupported content hash data`, "UNSUPPORTED_OPERATION", { - operation: "getContentHash()", - info: { data } - }); - } - - /** - * Resolves to the avatar url or ``null`` if the avatar is either - * unconfigured or incorrectly configured (e.g. references an NFT - * not owned by the address). - * - * If diagnosing issues with configurations, the [[_getAvatar]] - * method may be useful. - */ - async getAvatar(): Promise { - const avatar = await this._getAvatar(); - return avatar.url; - } - - /** - * When resolving an avatar, there are many steps involved, such - * fetching metadata and possibly validating ownership of an - * NFT. - * - * This method can be used to examine each step and the value it - * was working from. - */ - async _getAvatar(): Promise { - const linkage: Array = [ { type: "name", value: this.name } ]; - try { - // test data for ricmoo.eth - //const avatar = "eip155:1/erc721:0x265385c7f4132228A0d54EB1A9e7460b91c0cC68/29233"; - const avatar = await this.getText("avatar"); - if (avatar == null) { - linkage.push({ type: "!avatar", value: "" }); - return { url: null, linkage }; - } - linkage.push({ type: "avatar", value: avatar }); - - for (let i = 0; i < matchers.length; i++) { - const match = avatar.match(matchers[i]); - if (match == null) { continue; } - - const scheme = match[1].toLowerCase(); - - switch (scheme) { - case "https": - case "data": - linkage.push({ type: "url", value: avatar }); - return { linkage, url: avatar }; - case "ipfs": { - const url = getIpfsLink(avatar); - linkage.push({ type: "ipfs", value: avatar }); - linkage.push({ type: "url", value: url }); - return { linkage, url }; - } - - case "erc721": - case "erc1155": { - // Depending on the ERC type, use tokenURI(uint256) or url(uint256) - const selector = (scheme === "erc721") ? "tokenURI(uint256)": "uri(uint256)"; - linkage.push({ type: scheme, value: avatar }); - - // The owner of this name - const owner = await this.getAddress(); - if (owner == null) { - linkage.push({ type: "!owner", value: "" }); - return { url: null, linkage }; - } - - const comps = (match[2] || "").split("/"); - if (comps.length !== 2) { - linkage.push({ type: `!${ scheme }caip`, value: (match[2] || "") }); - return { url: null, linkage }; - } - - const tokenId = comps[1]; - - const contract = new Contract(comps[0], [ - // ERC-721 - "function tokenURI(uint) view returns (string)", - "function ownerOf(uint) view returns (address)", - - // ERC-1155 - "function uri(uint) view returns (string)", - "function balanceOf(address, uint256) view returns (uint)" - ], this.provider); - - // Check that this account owns the token - if (scheme === "erc721") { - const tokenOwner = await contract.ownerOf(tokenId); - - if (owner !== tokenOwner) { - linkage.push({ type: "!owner", value: tokenOwner }); - return { url: null, linkage }; - } - linkage.push({ type: "owner", value: tokenOwner }); - - } else if (scheme === "erc1155") { - const balance = await contract.balanceOf(owner, tokenId); - if (!balance) { - linkage.push({ type: "!balance", value: "0" }); - return { url: null, linkage }; - } - linkage.push({ type: "balance", value: balance.toString() }); - } - - // Call the token contract for the metadata URL - let metadataUrl = await contract[selector](tokenId); - if (metadataUrl == null || metadataUrl === "0x") { - linkage.push({ type: "!metadata-url", value: "" }); - return { url: null, linkage }; - } - - linkage.push({ type: "metadata-url-base", value: metadataUrl }); - - // ERC-1155 allows a generic {id} in the URL - if (scheme === "erc1155") { - metadataUrl = metadataUrl.replace("{id}", toBeHex(tokenId, 32).substring(2)); - linkage.push({ type: "metadata-url-expanded", value: metadataUrl }); - } - - // Transform IPFS metadata links - if (metadataUrl.match(/^ipfs:/i)) { - metadataUrl = getIpfsLink(metadataUrl); - } - linkage.push({ type: "metadata-url", value: metadataUrl }); - - // Get the token metadata - let metadata: any = { }; - const response = await (new FetchRequest(metadataUrl)).send(); - response.assertOk(); - - try { - metadata = response.bodyJson; - } catch (error) { - try { - linkage.push({ type: "!metadata", value: response.bodyText }); - } catch (error) { - const bytes = response.body; - if (bytes) { - linkage.push({ type: "!metadata", value: hexlify(bytes) }); - } - return { url: null, linkage }; - } - return { url: null, linkage }; - } - - if (!metadata) { - linkage.push({ type: "!metadata", value: "" }); - return { url: null, linkage }; - } - - linkage.push({ type: "metadata", value: JSON.stringify(metadata) }); - - // Pull the image URL out - let imageUrl = metadata.image; - if (typeof(imageUrl) !== "string") { - linkage.push({ type: "!imageUrl", value: "" }); - return { url: null, linkage }; - } - - if (imageUrl.match(/^(https:\/\/|data:)/i)) { - // Allow - } else { - // Transform IPFS link to gateway - const ipfs = imageUrl.match(matcherIpfs); - if (ipfs == null) { - linkage.push({ type: "!imageUrl-ipfs", value: imageUrl }); - return { url: null, linkage }; - } - - linkage.push({ type: "imageUrl-ipfs", value: imageUrl }); - imageUrl = getIpfsLink(imageUrl); - } - - linkage.push({ type: "url", value: imageUrl }); - - return { linkage, url: imageUrl }; - } - } - } - } catch (error) { } - - return { linkage, url: null }; - } - - static async getEnsAddress(provider: Provider): Promise { - const network = await provider.getNetwork(); - - const ensPlugin = network.getPlugin("org.quais.plugins.network.Ens"); - - // No ENS... - assert(ensPlugin, "network does not support ENS", "UNSUPPORTED_OPERATION", { - operation: "getEnsAddress", info: { network } }); - - return ensPlugin.address; - } - - static async #getResolver(provider: Provider, name: string): Promise { - const ensAddr = await EnsResolver.getEnsAddress(provider); - - try { - const contract = new Contract(ensAddr, [ - "function resolver(bytes32) view returns (address)" - ], provider); - - const addr = await contract.resolver(namehash(name), { - enableCcipRead: true - }); - - if (addr === ZeroAddress) { return null; } - return addr; - - } catch (error) { - // ENS registry cannot throw errors on resolver(bytes32), - // so probably a link error - throw error; - } - - return null; - } - - /** - * Resolve to the ENS resolver for %%name%% using %%provider%% or - * ``null`` if unconfigured. - */ - static async fromName(provider: AbstractProvider, name: string): Promise { - - let currentName = name; - while (true) { - if (currentName === "" || currentName === ".") { return null; } - - // Optimization since the eth node cannot change and does - // not have a wildcard resolver - if (name !== "eth" && currentName === "eth") { return null; } - - // Check the current node for a resolver - const addr = await EnsResolver.#getResolver(provider, currentName); - - // Found a resolver! - if (addr != null) { - const resolver = new EnsResolver(provider, addr, name); - - // Legacy resolver found, using EIP-2544 so it isn't safe to use - if (currentName !== name && !(await resolver.supportsWildcard())) { return null; } - - return resolver; - } - - // Get the parent node - currentName = currentName.split(".").slice(1).join("."); - } - } -} diff --git a/src.ts/providers/index.ts b/src.ts/providers/index.ts index f3b33ae2..a8804379 100644 --- a/src.ts/providers/index.ts +++ b/src.ts/providers/index.ts @@ -26,11 +26,6 @@ export { export { getDefaultProvider } from "./default-provider.js"; -export { - EnsResolver, - MulticoinProviderPlugin -} from "./ens-resolver.js"; - export { Network } from "./network.js"; export { NonceManager } from "./signer-noncemanager.js"; diff --git a/src.ts/providers/provider-jsonrpc.ts b/src.ts/providers/provider-jsonrpc.ts index 4ee203f0..99dbccd4 100644 --- a/src.ts/providers/provider-jsonrpc.ts +++ b/src.ts/providers/provider-jsonrpc.ts @@ -304,7 +304,7 @@ export class JsonRpcSigner extends AbstractSigner { if (tx.from) { const _from = tx.from; promises.push((async () => { - const from = await resolveAddress(_from, this.provider); + const from = await resolveAddress(_from); assertArgument(from != null && from.toLowerCase() === this.address.toLowerCase(), "from address mismatch", "transaction", _tx); tx.from = from; @@ -326,7 +326,7 @@ export class JsonRpcSigner extends AbstractSigner { if (tx.to != null) { const _to = tx.to; promises.push((async () => { - tx.to = await resolveAddress(_to, this.provider); + tx.to = await resolveAddress(_to); })()); } @@ -406,7 +406,7 @@ export class JsonRpcSigner extends AbstractSigner { // Make sure the from matches the sender if (tx.from) { - const from = await resolveAddress(tx.from, this.provider); + const from = await resolveAddress(tx.from); assertArgument(from != null && from.toLowerCase() === this.address.toLowerCase(), "from address mismatch", "transaction", _tx); tx.from = from; @@ -427,17 +427,10 @@ export class JsonRpcSigner extends AbstractSigner { async signTypedData(domain: TypedDataDomain, types: Record>, _value: Record): Promise { const value = deepCopy(_value); - - // Populate any ENS names (in-place) - const populated = await TypedDataEncoder.resolveNames(domain, types, value, async (value: string) => { - const address = await resolveAddress(value); - assertArgument(address != null, "TypedData does not support null address", "value", value); - return address; - }); - + return await this.provider.send("quai_signTypedData_v4", [ this.address.toLowerCase(), - JSON.stringify(TypedDataEncoder.getPayload(populated.domain, types, populated.value)) + JSON.stringify(TypedDataEncoder.getPayload(domain, types, value)) ]); } diff --git a/src.ts/providers/provider.ts b/src.ts/providers/provider.ts index 0e790858..6304ad2a 100644 --- a/src.ts/providers/provider.ts +++ b/src.ts/providers/provider.ts @@ -5,7 +5,7 @@ import { } from "../utils/index.js"; import { accessListify } from "../transaction/index.js"; -import type { AddressLike, NameResolver } from "../address/index.js"; +import type { AddressLike } from "../address/index.js"; import type { BigNumberish, EventEmitterable } from "../utils/index.js"; import type { Signature } from "../crypto/index.js"; import type { AccessList, AccessListish, TransactionLike } from "../transaction/index.js"; @@ -1870,7 +1870,7 @@ export type ProviderEvent = string | Array> | EventFilter * private key must be used to sign the transaction before it can be * broadcast. */ -export interface Provider extends ContractRunner, EventEmitterable, NameResolver { +export interface Provider extends ContractRunner, EventEmitterable { /** * The provider iteself. @@ -2017,25 +2017,6 @@ export interface Provider extends ContractRunner, EventEmitterable>; - - //////////////////// - // ENS - - /** - * Resolves to the address configured for the %%ensName%% or - * ``null`` if unconfigured. - */ - resolveName(ensName: string): Promise; - - /** - * Resolves to the ENS name associated for the %%address%% or - * ``null`` if the //primary name// is not configured. - * - * Users must perform additional steps to configure a //primary name//, - * which is not currently common. - */ - lookupAddress(address: string): Promise; - /** * Waits until the transaction %%hash%% is mined and has %%confirms%% * confirmations. diff --git a/src.ts/providers/signer.ts b/src.ts/providers/signer.ts index 02ba5dc6..bc1f3b47 100644 --- a/src.ts/providers/signer.ts +++ b/src.ts/providers/signer.ts @@ -1,5 +1,5 @@ -import type { Addressable, NameResolver } from "../address/index.js"; +import type { Addressable } from "../address/index.js"; import type { TypedDataDomain, TypedDataField } from "../hash/index.js"; import type { TransactionLike } from "../transaction/index.js"; @@ -14,7 +14,7 @@ import type { BlockTag, Provider, TransactionRequest, TransactionResponse } from * Signing entities, such as Smart Contract Wallets or Virtual Wallets (where the * private key may not be known). */ -export interface Signer extends Addressable, ContractRunner, NameResolver { +export interface Signer extends Addressable, ContractRunner { /** * The [[Provider]] attached to this Signer (if any). @@ -108,12 +108,6 @@ export interface Signer extends Addressable, ContractRunner, NameResolver { */ call(tx: TransactionRequest): Promise; - /** - * Resolves an ENS Name to an address. - */ - resolveName(name: string): Promise; - - //////////////////// // Signing diff --git a/src.ts/quais.ts b/src.ts/quais.ts index 2360b5c2..ac1a0853 100644 --- a/src.ts/quais.ts +++ b/src.ts/quais.ts @@ -14,7 +14,7 @@ export { } from "./abi/index.js"; export { - getAddress, getIcapAddress, + getAddress, getCreateAddress, getCreate2Address, isAddressable, isAddress, resolveAddress } from "./address/index.js"; @@ -69,12 +69,11 @@ export { IpcSocketProvider, SocketProvider, WebSocketProvider, - EnsResolver, Network, EnsPlugin, FeeDataNetworkPlugin, FetchUrlFeeDataNetworkPlugin, - GasCostPlugin, NetworkPlugin, MulticoinProviderPlugin, + GasCostPlugin, NetworkPlugin, SocketBlockSubscriber, SocketEventSubscriber, SocketPendingSubscriber, SocketSubscriber, UnmanagedSubscriber, @@ -141,7 +140,7 @@ export type { } from "./abi/index.js"; export type { - Addressable, AddressLike, NameResolver + Addressable, AddressLike } from "./address/index.js"; export type { @@ -191,8 +190,8 @@ export type { quaisError, UnknownError, NotImplementedError, UnsupportedOperationError, NetworkError, ServerError, TimeoutError, BadDataError, CancelledError, BufferOverrunError, NumericFaultError, InvalidArgumentError, MissingArgumentError, UnexpectedArgumentError, - CallExceptionError, InsufficientFundsError, NonceExpiredError, OffchainFaultError, - ReplacementUnderpricedError, TransactionReplacedError, UnconfiguredNameError, + CallExceptionError, InsufficientFundsError, NonceExpiredError, + ReplacementUnderpricedError, TransactionReplacedError, ActionRejectedError, CodedquaisError, diff --git a/src.ts/utils/errors.ts b/src.ts/utils/errors.ts index 6194ddfc..26bc4648 100644 --- a/src.ts/utils/errors.ts +++ b/src.ts/utils/errors.ts @@ -477,22 +477,6 @@ export interface NonceExpiredError extends quaisError<"NONCE_EXPIRED"> { transaction: TransactionRequest; } -/** - * A CCIP-read exception, which cannot be recovered from or - * be further processed. - */ -export interface OffchainFaultError extends quaisError<"OFFCHAIN_FAULT"> { - /** - * The transaction. - */ - transaction?: TransactionRequest; - - /** - * The reason the CCIP-read failed. - */ - reason: string; -} - /** * An attempt was made to replace a transaction, but with an * insufficient additional fee to afford evicting the old @@ -536,20 +520,6 @@ export interface TransactionReplacedError extends quaisError<"TRANSACTION_REPLAC receipt: TransactionReceipt; } -/** - * This Error indicates an ENS name was used, but the name has not - * been configured. - * - * This could indicate an ENS name is unowned or that the current - * address being pointed to is the [[ZeroAddress]]. - */ -export interface UnconfiguredNameError extends quaisError<"UNCONFIGURED_NAME"> { - /** - * The ENS name that was requested - */ - value: string; -} - /** * This Error indicates a request was rejected by the user. * @@ -602,10 +572,8 @@ export type CodedquaisError = T extends "CALL_EXCEPTION" ? CallExceptionError: T extends "INSUFFICIENT_FUNDS" ? InsufficientFundsError: T extends "NONCE_EXPIRED" ? NonceExpiredError: - T extends "OFFCHAIN_FAULT" ? OffchainFaultError: T extends "REPLACEMENT_UNDERPRICED" ? ReplacementUnderpricedError: T extends "TRANSACTION_REPLACED" ? TransactionReplacedError: - T extends "UNCONFIGURED_NAME" ? UnconfiguredNameError: T extends "ACTION_REJECTED" ? ActionRejectedError: diff --git a/src.ts/utils/index.ts b/src.ts/utils/index.ts index 6143470f..95f095f6 100644 --- a/src.ts/utils/index.ts +++ b/src.ts/utils/index.ts @@ -69,8 +69,8 @@ export type { quaisError, UnknownError, NotImplementedError, UnsupportedOperationError, NetworkError, ServerError, TimeoutError, BadDataError, CancelledError, BufferOverrunError, NumericFaultError, InvalidArgumentError, MissingArgumentError, UnexpectedArgumentError, - CallExceptionError, InsufficientFundsError, NonceExpiredError, OffchainFaultError, - ReplacementUnderpricedError, TransactionReplacedError, UnconfiguredNameError, + CallExceptionError, InsufficientFundsError, NonceExpiredError, + ReplacementUnderpricedError, TransactionReplacedError, ActionRejectedError, CallExceptionAction, CallExceptionTransaction, diff --git a/src.ts/wallet/base-wallet.ts b/src.ts/wallet/base-wallet.ts index be3e61b0..45452b99 100644 --- a/src.ts/wallet/base-wallet.ts +++ b/src.ts/wallet/base-wallet.ts @@ -3,7 +3,7 @@ import { hashMessage, TypedDataEncoder } from "../hash/index.js"; import { AbstractSigner } from "../providers/index.js"; import { computeAddress, Transaction } from "../transaction/index.js"; import { - resolveProperties, assert, assertArgument + resolveProperties, assertArgument } from "../utils/index.js"; import type { SigningKey } from "../crypto/index.js"; @@ -75,8 +75,8 @@ export class BaseWallet extends AbstractSigner { async signTransaction(tx: TransactionRequest ): Promise { // Replace any Addressable or ENS name with an address const { to, from } = await resolveProperties({ - to: (tx.to ? resolveAddress(tx.to, this.provider): undefined), - from: (tx.from ? resolveAddress(tx.from, this.provider): undefined) + to: (tx.to ? resolveAddress(tx.to): undefined), + from: (tx.from ? resolveAddress(tx.from): undefined) }); if (to != null) { tx.to = to; } @@ -110,25 +110,6 @@ export class BaseWallet extends AbstractSigner { } async signTypedData(domain: TypedDataDomain, types: Record>, value: Record): Promise { - - // Populate any ENS names - const populated = await TypedDataEncoder.resolveNames(domain, types, value, async (name: string) => { - // @TODO: this should use resolveName; addresses don't - // need a provider - - assert(this.provider != null, "cannot resolve ENS names without a provider", "UNSUPPORTED_OPERATION", { - operation: "resolveName", - info: { name } - }); - - const address = await this.provider.resolveName(name); - assert(address != null, "unconfigured ENS name", "UNCONFIGURED_NAME", { - value: name - }); - - return address; - }); - - return this.signingKey.sign(TypedDataEncoder.hash(populated.domain, types, populated.value)).serialized; + return this.signingKey.sign(TypedDataEncoder.hash(domain, types, value)).serialized; } }