Last active
October 6, 2023 19:26
-
-
Save drewstaylor/088af645dd36c013c02a2b4d05110479 to your computer and use it in GitHub Desktop.
ArchID 3rd party integration examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// You can check if domain name already exists by querying the | |
// `ResolveRecord` entry point of the Registry contract; however, | |
// it should be noted this query will return an error for domain | |
// names that are available, and a DNS record for domains that do | |
use cosmwasm_std::{to_binary, QueryRequest, WasmQuery,}; | |
use crate::archid_registry; | |
let registry_contract = "Registry contract address goes here"; | |
let desired_domain_name = "archid.arch"; | |
let query_msg: archid_registry::QueryMsg = archid_registry::ResolveRecord { | |
name: desired_domain_name.into(), | |
}; | |
let query_req = QueryRequest::Wasm(WasmQuery::Smart { | |
contract_addr: registry_contract.into(), | |
msg: to_binary(&query_msg).unwrap(), | |
}); | |
let query_resp = deps.querier.query(&query_req)?; | |
if query_resp.is_ok() { | |
// The desired domain has already been taken | |
} | |
if query_resp.is_err() { | |
// The desired domain is available | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Fetch an array of domain names that resolve to a specific `account` address | |
* returns an empty array, for the `names` member, if no valid domains resolve | |
* resolve to the `account` address | |
* @param {String} contract : contract address string for registry contract | |
* @param {String} account : account address to be queried | |
* @param {SigningCosmWasmClient} client : instance of signing client | |
* @returns {QueryResult} | |
*/ | |
async function DomainsOf(contract = null, account = null, client = null) { | |
try { | |
let entrypoint = { | |
resolve_address: { | |
address: account | |
} | |
}; | |
let namesQuery = await client.queryClient.wasm.queryContractSmart( | |
contract, | |
entrypoint | |
); | |
return namesQuery; | |
} catch(e) { | |
console.error(e); | |
return {}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// You can check if an address has one or more domains that | |
// resolve to it, using the `ResolveAddress` entry point | |
use cosmwasm_std::{Addr, to_binary, QueryRequest, WasmQuery,}; | |
use crate::archid_registry; | |
let registry_contract = "Registry contract address goes here"; | |
let address_to_be_checked: Addr = "archway1f395p0gg67mmfd5zcqvpnp9cxnu0hg6r9hfczq"; | |
let query_msg: archid_registry::QueryMsg = archid_registry::ResolveAddress { | |
address: address_to_be_checked, | |
}; | |
let query_req = QueryRequest::Wasm(WasmQuery::Smart { | |
contract_addr: registry_contract.into(), | |
msg: to_binary(&query_msg).unwrap(), | |
}); | |
let query_resp = deps.querier.query(&query_req)?; | |
if query_resp.names.unwrap().is_none() { | |
// The address has no valid domain names | |
} else { | |
// query_resp.names is a vector of valid domain names that | |
// resolve to `address_to_be_checked` | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Loads token ids owned by a specific address | |
* @param {String} contract : contract address string for token contract | |
* @param {String} account : owner account address to be queried | |
* @param {SigningCosmWasmClient} client : (Optional) instance of signing client | |
* @param {Number} limit? : (Optional) max amount of tokens to be loaded; defaults to 100 | |
* @param {String} start_after? : (Optional) `tokenId` for pagination, begin loading tokens beginning after a specific `tokenId` | |
* @returns {QueryResult} | |
*/ | |
async function TokensOf(contract = null, account = null, client = null, limit = 100, start_after = null) { | |
try { | |
let entrypoint = { | |
tokens: { | |
owner: account, | |
limit: limit, | |
} | |
}; | |
if (start_after) entrypoint.tokens["start_after"] = start_after; | |
let tokenQuery = await client.queryClient.wasm.queryContractSmart( | |
contract, | |
entrypoint | |
); | |
return tokenQuery; | |
} catch(e) { | |
console.error(e); | |
return {}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// These types are also needed if you are importing the Registry | |
// contract types (e.g. in order to integrate contract-to-contract | |
// calls to the Registry contract) | |
use schemars::JsonSchema; | |
use serde::{Deserialize, Serialize}; | |
#[allow(clippy::derive_partial_eq_without_eq)] | |
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] | |
pub struct Subdomain { | |
pub name: Option<String>, | |
pub resolver: Option<Addr>, | |
pub minted: Option<bool>, | |
pub created: Option<u64>, | |
pub expiry: Option<u64>, | |
} | |
#[allow(clippy::derive_partial_eq_without_eq)] | |
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] | |
pub struct Account { | |
pub username: Option<String>, | |
pub profile: Option<String>, | |
pub account_type: Option<String>, | |
pub verfication_hash: Option<String>, | |
} | |
#[allow(clippy::derive_partial_eq_without_eq)] | |
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] | |
pub struct Website { | |
pub url: Option<String>, | |
pub domain: Option<String>, | |
pub verfication_hash: Option<String>, | |
} | |
#[allow(clippy::derive_partial_eq_without_eq)] | |
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] | |
pub struct Metadata { | |
pub name: Option<String>, // e.g. for interoperability with external marketplaces | |
pub description: Option<String>, // e.g. ibid. | |
pub image: Option<String>, // e.g. ibid. | |
pub created: Option<u64>, | |
pub expiry: Option<u64>, | |
pub domain: Option<String>, | |
pub subdomains: Option<Vec<Subdomain>>, | |
pub accounts: Option<Vec<Account>>, | |
pub websites: Option<Vec<Website>>, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const REGISTRY_CONTRACT = "Registry contract address goes here"; | |
/** | |
* Read the contract Config; | |
* Use this to get the base_cost (cost per year) of registering a domain | |
* @param {SigningCosmWasmClient} client? : (Optional) instance of signing client | |
* @returns {QueryResult} | |
*/ | |
async function Config(client = null) { | |
try { | |
let entrypoint = { | |
config: {} | |
}; | |
let query = await client.queryClient.wasm.queryContractSmart( | |
REGISTRY_CONTRACT, | |
entrypoint | |
); | |
return query; | |
} catch(e) { | |
console.error(e); | |
return {error: e}; | |
} | |
} | |
/* | |
Example return: | |
Config(cwClient)l | |
//returns: | |
{ | |
"admin":"archway1f395p0gg67mmfd5zcqvpnp9cxnu0hg6r9hfczq", | |
"wallet":"archway1f395p0gg67mmfd5zcqvpnp9cxnu0hg6r9hfczq", | |
"cw721":"archway1ll9jnzdnge45w56tas3m2z08hhevwykj8hmgxpa4mfppdrx2ztfsxmj0fl", | |
"base_cost":"50000", | |
"base_expiration":10000000 | |
} | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Get the per year cost of registering a domain name | |
// by querying the `Config` entry point of the Registry | |
// contract. This query entry point takes no parameters | |
// as arguments (e.g. `{}`). Domains can be registered | |
// for 1, 2 or 3 years. Paying more than 3 x the base per | |
// year cost, will result in a registration of 3 years. | |
use cosmwasm_std::{to_binary, QueryRequest, WasmQuery,}; | |
use crate::archid_registry; | |
let registry_contract = "Registry contract address goes here"; | |
let desired_domain_name = "archid.arch"; | |
let query_msg: archid_registry::QueryMsg = archid_registry::Config {}; | |
let query_req = QueryRequest::Wasm(WasmQuery::Smart { | |
contract_addr: registry_contract.into(), | |
msg: to_binary(&query_msg).unwrap(), | |
}); | |
let query_resp = deps.querier.query(&query_req)?; | |
let cost_per_year = query_resp.base_cost.unwrap(); | |
// Note: `cost_per_year` will be a string value in `aarch` (or `aconst` if using testnet) | |
// You'll need to convert it to int to do math on it (e.g. to register for multiple | |
// years) or to register the domain using the `Register` entry point. Example conversion: | |
// `let integer_cost_per_year = cost_per_year.parse::<u128>().unwrap()` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { coin } from "@cosmjs/stargate"; | |
const REGISTRY_CONTRACT = "Registry contract address goes here"; | |
/** | |
* Register a new ArchID domain | |
* @param {String} name : Domain name to be registered | |
* @param {Number} base_cost: The `base_cost` value as defined in the Registry contract storage | |
* @param {Number} years : Number of years to be registered; an integer between 1 and 3, impacts cost | |
* @param {String} sender : The address of the party registering the domain | |
* @param {SigningCosmWasmClient} client? : instance of signing client | |
* @see {Config()} | |
* @returns {ExecuteResult} | |
*/ | |
async function Register(name, years = 1, base_cost = 0, sender = null, client = null) { | |
try { | |
let entrypoint = { | |
register: { | |
name: name | |
} | |
}; | |
// Purchase cost | |
let denom = "aconst"; // "aconst" is for `constantine-3`; for `constantine-2` use "uconst" | |
let funds = [coin((base_cost * years), denom)]; | |
// Broadcast tx | |
let tx = await client.execute( | |
sender, | |
REGISTRY_CONTRACT, | |
entrypoint, | |
client.fees, | |
"Registering domain", | |
funds | |
); | |
// Tx result | |
return tx; | |
} catch (e) { | |
return {error: e}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Register a domain name | |
use cosmwasm_std::{CosmosMsg, WasmMsg, Coin, to_binary, Uint128,}; | |
use archid_registry::{ | |
ExecuteMsg as ArchIdExecuteMsg, | |
}; | |
let registry_contract = "Registry contract address goes here"; | |
let desired_domain_name = "archid"; // XXX: Do not add the `.arch` suffix when registering a domain | |
// XXX: Remember to get the actual cost per year by querying the `Config` entry point (see above example) | |
let cost_per_year: u128 = 250000000000000000; | |
let denom = "aarch"; // (Or "aconst" for testnet) | |
let register_msg: archid_registry::ExecuteMsg = ArchIdExecuteMsg::Register { | |
name: desired_domain_name.into(), | |
}; | |
let register_resp: CosmosMsg = WasmMsg::Execute { | |
contract_addr: registry_contract.into(), | |
msg: to_binary(®ister_msg)?, | |
funds: &[Coin { | |
denom: denom.into(), | |
amount: Uint128::from(cost_per_year), | |
}], | |
} | |
.into(); | |
let messages = vec![register_resp]; | |
Ok(Response::new().add_messages(messages)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// You'll need to import these types if you want to make contract-to-contract | |
// calls to the ArchID Registry contract | |
use archid_token::{Account, Website}; | |
use cosmwasm_std::{Addr, Uint128}; | |
use schemars::JsonSchema; | |
use serde::{Deserialize, Serialize}; | |
// The following types come from `src/state.rs` in the Registry project | |
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] | |
pub struct Config { | |
pub admin: Addr, | |
pub wallet: Addr, | |
pub cw721: Addr, | |
pub base_cost: Uint128, | |
pub base_expiration: u64, | |
} | |
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] | |
pub enum SubDomainStatus { | |
//if subdomain in acive mint domain owner can only extend expiration up to domain expiration | |
ExistingMintActive, | |
// if subdomain expired owner can remint which will first burn existing nft | |
ExistingMintExpired, | |
// if new subdomain owner can register and mint / not mint | |
NewSubdomain | |
} | |
// The following types come from `src/msg.rs` in the Registry project | |
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] | |
pub struct InstantiateMsg { | |
pub admin: Addr, | |
pub wallet: Addr, | |
pub cw721: Addr, | |
pub base_cost: Uint128, | |
pub base_expiration: u64, | |
} | |
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] | |
pub struct MetaDataUpdateMsg { | |
pub description: Option<String>, | |
pub image: Option<String>, | |
pub accounts: Option<Vec<Account>>, | |
pub websites: Option<Vec<Website>>, | |
} | |
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] | |
#[serde(rename_all = "snake_case")] | |
pub enum ExecuteMsg { | |
Register { | |
name: String, | |
}, | |
Withdraw { | |
amount: Uint128, | |
}, | |
RenewRegistration { | |
name: String, | |
}, | |
ExtendSubdomainExpiry { | |
domain: String, | |
subdomain: String, | |
expiration: u64, | |
}, | |
UpdateResolver { | |
name: String, | |
new_resolver: Addr, | |
}, | |
RegisterSubdomain { | |
domain: String, | |
subdomain: String, | |
new_resolver: Addr, | |
new_owner: Addr, | |
expiration: u64, | |
}, | |
RemoveSubdomain { | |
domain: String, | |
subdomain: String, | |
}, | |
UpdateConfig { | |
config: Config, | |
}, | |
UpdateUserDomainData { | |
name: String, | |
metadata_update: MetaDataUpdateMsg, | |
}, | |
} | |
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] | |
#[serde(rename_all = "snake_case")] | |
pub enum QueryMsg { | |
ResolveRecord { name: String }, | |
RecordExpiration { name: String }, | |
ResolveAddress { address: Addr }, | |
Config {}, | |
} | |
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] | |
pub struct ResolveRecordResponse { | |
pub address: Option<String>, | |
pub expiration: u64, | |
} | |
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] | |
pub struct ResolveAddressResponse { | |
pub names: Option<Vec<String>>, | |
} | |
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] | |
pub struct RecordExpirationResponse { | |
pub created: u64, | |
pub expiration: u64, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const REGISTRY_CONTRACT = "Registry contract address goes here"; | |
/** | |
* Resolve a Domain name record from the registry contract | |
* @param {String} name : Domain name to be resolved | |
* @param {SigningCosmWasmClient} client? : instance of signing client | |
* @returns {QueryResult} | |
*/ | |
async function ResolveRecord(name, client = null) { | |
try { | |
let entrypoint = { | |
resolve_record: { | |
name: name | |
} | |
}; | |
let query = await client.queryClient.wasm.queryContractSmart( | |
REGISTRY_CONTRACT, | |
entrypoint | |
); | |
return query; | |
} catch(e) { | |
return {error: e}; | |
} | |
} | |
/* | |
Example return: | |
ResolveRecord('nft.arch', cwClient); | |
//returns: | |
{ address: "archway1h3mqe7elgk0ndjc5yfw8kv92m449y4e3k84pa2", expiration: 1693037996 } | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Load token metadata from token contract for a valid token ID | |
* @param {String} tokenId : The domain name / token ID to be fetched | |
* @param {String} contract : contract address string for token contract | |
* @param {SigningCosmWasmClient} client : instance of signing client | |
* @returns {QueryResult} | |
*/ | |
async function Token (tokenId = null, contract = null, client = null) { | |
try { | |
let entrypoint = { | |
nft_info: { | |
token_id: tokenId | |
} | |
}; | |
let tokenQuery = await client.queryClient.wasm.queryContractSmart( | |
contract, | |
entrypoint | |
); | |
return tokenQuery; | |
} catch(e) { | |
return {error: e}; | |
} | |
} | |
/* | |
Example return: | |
const cw721ContractAddress = "nft contract address goes here"; | |
Token('archid.arch', cw721ContractAddress, cwClient); | |
//returns: | |
{ | |
"token_uri": null, | |
"extension": { | |
"name": "archid.arch", | |
"description": "A decentralized name service with support for domains, subdomains, and web2 identity verifcation", | |
"image": "ipfs://QmNoMUgTM82EGaTCTnuEUJDusV21UEGSgKM5RhM1C9N3WE", | |
"created": 1680023536, | |
"expiry": 1710023536, | |
"domain": "archid.arch", | |
"subdomains": [ | |
{ | |
"name": "dapp", | |
"resolver": "archway100vemsuja6h7k5ygve3xz3yzgapdj6zpe00ffg8d95hpwj9d8v5q8zc9zh", | |
"minted": true, | |
"created": 1680023944, | |
"expiry": 1705788708 | |
}, | |
{ | |
"name": "token", | |
"resolver": "archway1ll9jnzdnge45w56tas3m2z08hhevwykj8hmgxpa4mfppdrx2ztfsxmj0fl", | |
"minted": true, | |
"created": 1682367218, | |
"expiry": 1710023536 | |
} | |
], | |
"accounts": [ | |
{ | |
"username": "@archidapp", | |
"profile": "https://twitter.com/archidapp", | |
"account_type": "twitter", | |
"verfication_hash": null | |
}, | |
{ | |
"username": "archid-protocol", | |
"profile": "https://github.com/archid-protocol", | |
"account_type": "github", | |
"verfication_hash": null | |
} | |
], | |
"websites": [ | |
{ | |
"url": "https://archid.app", | |
"domain": "dapp.archid.arch", | |
"verfication_hash": null | |
} | |
] | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment