checks.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import { assert, assertArgument } from "../utils/index.js";
  2. import { getAddress } from "./address.js";
  3. import type { Addressable, AddressLike, NameResolver } from "./index.js";
  4. /**
  5. * Returns true if %%value%% is an object which implements the
  6. * [[Addressable]] interface.
  7. *
  8. * @example:
  9. * // Wallets and AbstractSigner sub-classes
  10. * isAddressable(Wallet.createRandom())
  11. * //_result:
  12. *
  13. * // Contracts
  14. * contract = new Contract("dai.tokens.ethers.eth", [ ], provider)
  15. * isAddressable(contract)
  16. * //_result:
  17. */
  18. export function isAddressable(value: any): value is Addressable {
  19. return (value && typeof(value.getAddress) === "function");
  20. }
  21. /**
  22. * Returns true if %%value%% is a valid address.
  23. *
  24. * @example:
  25. * // Valid address
  26. * isAddress("0x8ba1f109551bD432803012645Ac136ddd64DBA72")
  27. * //_result:
  28. *
  29. * // Valid ICAP address
  30. * isAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK36")
  31. * //_result:
  32. *
  33. * // Invalid checksum
  34. * isAddress("0x8Ba1f109551bD432803012645Ac136ddd64DBa72")
  35. * //_result:
  36. *
  37. * // Invalid ICAP checksum
  38. * isAddress("0x8Ba1f109551bD432803012645Ac136ddd64DBA72")
  39. * //_result:
  40. *
  41. * // Not an address (an ENS name requires a provided and an
  42. * // asynchronous API to access)
  43. * isAddress("ricmoo.eth")
  44. * //_result:
  45. */
  46. export function isAddress(value: any): value is string {
  47. try {
  48. getAddress(value);
  49. return true;
  50. } catch (error) { }
  51. return false;
  52. }
  53. async function checkAddress(target: any, promise: Promise<null | string>): Promise<string> {
  54. const result = await promise;
  55. if (result == null || result === "0x0000000000000000000000000000000000000000") {
  56. assert(typeof(target) !== "string", "unconfigured name", "UNCONFIGURED_NAME", { value: target });
  57. assertArgument(false, "invalid AddressLike value; did not resolve to a value address", "target", target);
  58. }
  59. return getAddress(result);
  60. }
  61. /**
  62. * Resolves to an address for the %%target%%, which may be any
  63. * supported address type, an [[Addressable]] or a Promise which
  64. * resolves to an address.
  65. *
  66. * If an ENS name is provided, but that name has not been correctly
  67. * configured a [[UnconfiguredNameError]] is thrown.
  68. *
  69. * @example:
  70. * addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F"
  71. *
  72. * // Addresses are return synchronously
  73. * resolveAddress(addr, provider)
  74. * //_result:
  75. *
  76. * // Address promises are resolved asynchronously
  77. * resolveAddress(Promise.resolve(addr))
  78. * //_result:
  79. *
  80. * // ENS names are resolved asynchronously
  81. * resolveAddress("dai.tokens.ethers.eth", provider)
  82. * //_result:
  83. *
  84. * // Addressable objects are resolved asynchronously
  85. * contract = new Contract(addr, [ ])
  86. * resolveAddress(contract, provider)
  87. * //_result:
  88. *
  89. * // Unconfigured ENS names reject
  90. * resolveAddress("nothing-here.ricmoo.eth", provider)
  91. * //_error:
  92. *
  93. * // ENS names require a NameResolver object passed in
  94. * // (notice the provider was omitted)
  95. * resolveAddress("nothing-here.ricmoo.eth")
  96. * //_error:
  97. */
  98. export function resolveAddress(target: AddressLike, resolver?: null | NameResolver): string | Promise<string> {
  99. if (typeof(target) === "string") {
  100. if (target.match(/^0x[0-9a-f]{40}$/i)) { return getAddress(target); }
  101. assert(resolver != null, "ENS resolution requires a provider",
  102. "UNSUPPORTED_OPERATION", { operation: "resolveName" });
  103. return checkAddress(target, resolver.resolveName(target));
  104. } else if (isAddressable(target)) {
  105. return checkAddress(target, target.getAddress());
  106. } else if (target && typeof(target.then) === "function") {
  107. return checkAddress(target, target);
  108. }
  109. assertArgument(false, "unsupported addressable value", "target", target);
  110. }