UnstoppableDomainsResolution
解析是一个用于与区块链域名交互的库。它可以用来检索去中心化网站的付款地址和IPFS散列。
解析主要由Unstoppable Domains建立和维护。
安装resolution-swift
Cocoa Pods
pod 'UnstoppableDomainsResolution', '~> 6.1.0'
Swift 包管理器
package.dependencies.append(
.package(url: "https://github.com/unstoppabledomains/resolution-swift", from: "6.1.0")
)
更新库
Cocoa Pods
pod update UnstoppableDomainsResolution
Swift 包管理器
package.dependencies.append(
.package(url: "https://github.com/unstoppabledomains/resolution-swift", from: "<latest version number>")
)
使用解析
- 创建 Resolution 类的一个实例
- 异步调用 Resolution 类的任何方法
注意:确保在异步调用带来结果之前,不要释放 Resolution 类的实例。您的代码是实例的 唯一所有者,因此根据需要保留它。
使用Unstoppable Domains代理提供程序初始化
import UnstoppableDomainsResolution
// obtain a key by following this document https://docs.unstoppabledomains.com/domain-distribution-and-management/quickstart/retrieve-an-api-key/#api-key
guard let resolution = try? Resolution(apiKey: "<api_key>") else {
print ("Init of Resolution instance failed...")
return
}
注意:`apiKey`仅用于解析UNS的域名。在后台,它仍然使用默认的ZNS(Zilliqa)RPC url。为了更灵活的控制,请指定您的ZNS配置。
import UnstoppableDomainsResolution
// obtain a key by following this document https://docs.unstoppabledomains.com/domain-distribution-and-management/quickstart/retrieve-an-api-key/#api-key
guard let resolution = try? Resolution(
apiKey: "<api_key>",
znsLayer: NamingServiceConfig(
providerUrl: "https://api.zilliqa.com",
network: "mainnet")
) else {
print ("Init of Resolution instance with default parameters failed...")
return
}
使用自定义Ethereum配置初始化
用于配置每个连接的命名服务的Configurations
结构。库目前支持三个网络:Ethereum、Polygon和Zilliqa。您可以分别更新每个网络。
import UnstoppableDomainsResolution
// obtain a key from https://www.infura.io
let resolution = try Resolution(configs: Configurations(
uns: UnsLocations = UnsLocations(
layer1: NamingServiceConfig(
providerUrl: "https://mainnet.infura.io/v3/<infura_api_key>",
network: "mainnet"),
layer2: NamingServiceConfig(
providerUrl: "https://polygon-mainnet.infura.io/v3/<infura_api_key>",
network: "polygon-mainnet"),
znsLayer: NamingServiceConfig(
providerUrl: "https://api.zilliqa.com",
network: "mainnet")
)
);
示例
获取域名的加密地址
addr(domain: String, ticker: String)
此API用于查询单个地址记录的钱包地址。(请参见加密货币支付部分获取记录格式)
在brad.crypto
中有crypto.ETH.address
链上地址
resolution.addr(domain: "brad.crypto", ticker: "eth") { (result) in
switch result {
case .success(let returnValue):
ethAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected Eth Address, but got \(error)")
}
}
multiChainAddress(domain: String, ticker: String, chain: String)
此API用于查询多链地址记录的钱包地址。(请参见多链货币)
在brad.crypto
中有crypto.USDT.version.ERC20.address
和crypto.USDT.version.OMNI.address
链上地址
resolution.multiChainAddress(domain: "brad.crypto", ticker: "USDT", chain: "ERC20") { (result) in
switch result {
case .success(let returnValue):
ethAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected Eth Address, but got \(error)")
}
}
addr(domain: String, network: String, token: String)
(Beta版本)此API可用于查询单链和多链地址记录的钱包地址
在brad.crypto
中有crypto.ETH.address
和crypto.USDT.version.ERC20.address
链上地址
// single chain address
resolution.addr(domain: "brad.crypto", network: "eth", token: "eth") { (result) in
switch result {
case .success(let returnValue):
ethAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected Eth Address, but got \(error)")
}
}
// multi-chain address
resolution.multiChainAddress(domain: "brad.crypto", ticker: "ETH", chain: "USDT") { (result) in
switch result {
case .success(let returnValue):
usdtAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected USDT Address, but got \(error)")
}
}
注意该API将推断
ERC20
标准为ETH
网络。
API还可以由加密交易所用于推断钱包地址。在中心化交易所中,用户在不同网络上拥有相同钱包家庭的相同钱包地址。
使用brad.crypto
仅在链上只有token.EVM.address
记录。该API将解析EVM兼容网络上存在的代币的相同钱包地址。
// infer USDT on ETH network
resolution.multiChainAddress(domain: "brad.crypto", network: "ETH", token: "USDT") { (result) in
switch result {
case .success(let returnValue):
usdtOnEthAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected USDT Address, but got \(error)")
}
}
// infer ETH token on ETH network
resolution.multiChainAddress(domain: "brad.crypto", network: "ETH", token: "ETH") { (result) in
switch result {
case .success(let returnValue):
ethTokenOnEthAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected Eth Address, but got \(error)")
}
}
// infer USDT token on ETH network
resolution.multiChainAddress(domain: "brad.crypto", network: "AVAX", token: "USDT") { (result) in
switch result {
case .success(let returnValue):
usdtOnAvaxAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected USDT Address, but got \(error)")
}
}
使用brad.crypto
仅在链上只有token.EVM.ETH.address
记录。该API将为特定于以太坊网络的代币解析相同的钱包地址。
// infer USDT on ETH network
resolution.multiChainAddress(domain: "brad.crypto", network: "ETH", token: "USDT") { (result) in
switch result {
case .success(let returnValue):
usdtOnEthAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected USDT Address, but got \(error)")
}
}
// infer ETH token on ETH network
resolution.multiChainAddress(domain: "brad.crypto", network: "ETH", token: "ETH") { (result) in
switch result {
case .success(let returnValue):
ethTokenOnEthAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected Eth Address, but got \(error)")
}
}
// the API try to derive address for Avalanche network
resolution.multiChainAddress(domain: "brad.crypto", network: "AVAX", token: "USDT") { (result) in
switch result {
case .success(let returnValue):
usdtOnAvaxAddress = returnValue
domainReceived.fulfill()
case .failure(let error):
XCTFail("Expected USDT Address, but got \(error)")
}
}
该API与其他地址格式兼容。如果一个域名设置了多种地址格式,它将按照以下算法进行
如果一个域名设置了以下记录
token.EVM.address
crypto.USDC.version.ERC20.address
token.EVM.ETH.USDC.address
crypto.USDC.address
token.EVM.ETH.address
getAddress(domain, 'ETH', 'USDC')
将按照以下顺序查找记录
1. token.EVM.ETH.USDC.address
2. crypto.USDC.address
3. crypto.USDC.version.ERC20.address
4. token.EVM.ETH.address
5. token.EVM.address
批量请求所有者
此batchOwners(domains: _, completion: _ )
方法在执行多个域名所有者查询时提供了额外的便利。
此方法仅与uns-based域名兼容。使用此方法与其他任何域名类型将抛出错误:
ResolutionError.methodNotSupported
。
与单一的owner(domain: _, completion: _)
方法相比,此批量请求将返回所有者字符串数组[String?]
。如果域名未注册或其值为空,则响应中对应数组元素将保留为空,而不会抛出错误。
resolution.batchOwners(domains: ["brad.crypto", "homecakes.crypto"]) { result in
switch result {
case .success(let returnValue):
// returnValue: [String: String?] = <map of domains to owner address>
let domainOwner = returnValue
case .failure(let error):
XCTFail("Expected owner, but got \(error)")
}
}
resolution.locations(domains: ["brad.crypto", "homecakes.crypto"]) { result in
switch result {
case .success(let returnValue):
// returnValue: [String: String?] = <map of domains to domain locations>
let locations = returnValue
case .failure(let error):
XCTFail("Expected owner, but got \(error)")
}
}
网络
请确保您的应用有AppTransportSecurity设置,允许对
https://main-rpc.linkpool.io
域的HTTP访问。
自定义网络层
默认情况下,此库使用原生的iOS网络API连接到互联网。如果想让库使用自己的网络层,则必须使您的网络层符合《NetworkingLayer》协议。此协议需要实现三个方法
func makeHttpPostRequest(url:, httpMethod:, httpHeaderContentType:, httpBody:, completion:)
func makeHttpGetRequest(url: URL, completion:)
mutating func addHeader(header: String, value: String)
使用这些方法将绕过默认行为并将请求委托给您的网络代码。
例如,如此构建Resolution实例
let customNetworking = MyNetworkingApi()
let resolution = try Resolution(configs: Configurations(
uns: UnsLocations = UnsLocations(
layer1: NamingServiceConfig(
providerUrl: "https://mainnet.infura.io/v3/<infura_api_key>",
network: "mainnet",
networking: customNetworking),
layer2: NamingServiceConfig(
providerUrl: "https://polygon-mainnet.infura.io/v3/<infura_api_key>",
network: "polygon-mainnet",
networking: customNetworking),
znsLayer: NamingServiceConfig(
providerUrl: "https://api.zilliqa.com",
network: "mainnet")
)
);
可能错误
如果尝试解析的域未注册或不含所请求的信息,此框架将返回带有以下可能原因的《ResolutionError》。我们建议根据错误的返回值在你的应用程序中创建自定义错误。
enum ResolutionError: Error {
case unregisteredDomain
case unsupportedDomain
case recordNotFound
case recordNotSupported
case unsupportedNetwork
case unspecifiedResolver
case unknownError
case proxyReaderNonInitialized
case registryAddressIsNotProvided
case inconsistentDomainArray
case methodNotSupported
case tooManyResponses
case executionReverted
case badRequestOrResponse
case unsupportedServiceName
case invalidDomainName
case contractNotInitialized
case reverseResolutionNotSpecified
case unauthenticatedRequest
case requestBeingRateLimited
}
请参阅Resolution-Swift 错误代码页面以获取特定错误代码的详细信息。
贡献
非常欢迎对该库做出贡献。最简单的方式来贡献是通过GitHub问题和拉取请求。
构建 & 测试
决议库依赖环境变量来加载数字测试网络RPC URL。这样,我们的密钥不会直接暴露给代码。这些环境变量包括:
- L1_TEST_NET_RPC_URL
- L2_TEST_NET_RPC_URL
使用swift build
进行构建,使用swift test -v
运行测试
为整合软件免费推广
一旦您的应用程序成功集成了Unstoppable Domains,请在此处注册:https://unstoppabledomains.com/app-submission。注册的应用程序将出现在Unstoppable Domains的主页和应用程序页面上——每天都能将您的应用程序展示给成千上万可能的客户。
此外,我们每周都会从新整合的应用程序中挑选一个在Unstoppable Update时事通信中进行宣传。这份时事通信直接发送到大约10万位加密爱好者——他们中的每一位都可能成为您业务的新客户。
获取帮助
加入我们的Discord社区并提问。
帮助我们改进
我们一直在寻找方法改进开发者如何将我们的产品集成到他们的应用程序中。我们非常乐意听取您的体验,通过完成我们的调查来帮助我们改进。