@unique-nft/api
Version:
Definitely typed JS API for the Unique Network blockchain
188 lines (169 loc) • 6.02 kB
text/typescript
import {COLLECTION_ADDRESS_PREFIX, NESTING_PREFIX} from './constants'
import {
addressToEvm, compareSubstrateAddresses,
decodeSubstrateAddress, encodeSubstrateAddress,
evmToAddress,
normalizeSubstrateAddress
} from './substrate'
import {
collectionIdAndTokenIdToNestingAddress,
collectionIdToEthAddress, compareEthereumAddresses,
ethAddressToCollectionId,
nestingAddressToCollectionIdAndTokenId,
normalizeEthereumAddress
} from './ethereum'
import {
CrossAccountId, CrossAccountIdUncapitalized,
EthAddressObj, EthAddressObjUncapitalized,
SubAddressObj, SubAddressObjUncapitalized,
} from "../../types";
import {
substrateNormalizedWithMirrorIfEthereum,
addressToCrossAccountId, addressToCrossAccountIdNormalized,
guessAddressAndExtractItNormalized,
guessAddressAndExtractItNormalizedSafe
} from "./crossAccountId";
import * as StringUtils from './stringUtils'
import * as algorithms from './imports'
import * as constants from './constants'
export {constants, algorithms, StringUtils}
const ETH_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/
export type DecodeSubstrateAddressResult = {
u8a: Uint8Array,
hex: string,
bigint: bigint
}
export const validate = {
substrateAddress: (address: string) => {
decodeSubstrateAddress(address)
return true
},
ethereumAddress: (address: string) => {
if (!is.ethereumAddress(address)) {
throw new Error(`address "${address}" is not valid ethereum address`)
}
return true
},
collectionAddress: (address: string) => {
if (!is.collectionAddress(address)) {
throw new Error(`address ${address} is not a collection address`)
}
return true
},
nestingAddress: (address: string) => {
if (!is.nestingAddress(address)) {
throw new Error(`address ${address} is not a nesting address`)
}
return true
},
collectionId: (collectionId: number) => {
if (!is.collectionId(collectionId)) {
throw new Error(`collectionId should be a number between 0 and 0xffffffff`)
}
return true
},
tokenId: (tokenId: number) => {
if (!is.tokenId(tokenId)) {
throw new Error(`collectionId should be a number between 0 and 0xffffffff`)
}
return true
},
}
export const is = {
substrateAddress: (address: string): boolean => {
try {
decodeSubstrateAddress(address)
return true
} catch {
return false
}
},
ethereumAddress: (address: string): boolean => {
return typeof address === 'string' && address.length === 42 && !!address.match(ETH_ADDRESS_REGEX)
},
collectionAddress: (address: string): boolean => {
return is.ethereumAddress(address) && address.toLowerCase().startsWith(COLLECTION_ADDRESS_PREFIX)
},
nestingAddress: (address: string): boolean => {
return is.ethereumAddress(address) && address.toLowerCase().startsWith(NESTING_PREFIX)
},
collectionId: (collectionId: number): boolean => {
return !(typeof collectionId !== 'number' || isNaN(collectionId) || collectionId < 0 || collectionId > 0xffffffff)
},
tokenId: (tokenId: number): boolean => {
return !(typeof tokenId !== 'number' || isNaN(tokenId) || tokenId < 0 || tokenId > 0xffffffff)
},
crossAccountId(obj: any): obj is CrossAccountId {
return is.substrateAddressObject(obj) || is.ethereumAddressObject(obj)
},
crossAccountIdUncapitalized(obj: any): obj is CrossAccountIdUncapitalized {
return is.substrateAddressObjectUncapitalized(obj) || is.ethereumAddressObjectUncapitalized(obj)
},
substrateAddressObject(obj: any): obj is SubAddressObj {
return typeof obj === 'object' && typeof obj?.Substrate === 'string' && is.substrateAddress(obj.Substrate)
},
ethereumAddressObject(obj: any): obj is EthAddressObj {
return typeof obj === 'object' && typeof obj?.Ethereum === 'string' && is.ethereumAddress(obj.Ethereum)
},
substrateAddressObjectUncapitalized(obj: any): obj is SubAddressObjUncapitalized {
return typeof obj === 'object' && typeof obj?.substrate === 'string' && is.substrateAddress(obj.substrate)
},
ethereumAddressObjectUncapitalized(obj: any): obj is EthAddressObjUncapitalized {
return typeof obj === 'object' && typeof obj?.ethereum === 'string' && is.ethereumAddress(obj.ethereum)
},
}
export const collection = {
idToAddress: collectionIdToEthAddress,
addressToId: ethAddressToCollectionId,
}
export const nesting = {
idsToAddress: collectionIdAndTokenIdToNestingAddress,
addressToIds: nestingAddressToCollectionIdAndTokenId,
}
export const to = {
crossAccountId: addressToCrossAccountId,
crossAccountIdNormalized: addressToCrossAccountIdNormalized,
substrateNormalizedOrMirrorIfEthereum: substrateNormalizedWithMirrorIfEthereum,
}
export const extract = {
normalizedAddressFromObject: guessAddressAndExtractItNormalized,
normalizedAddressFromObjectSafe: guessAddressAndExtractItNormalizedSafe,
crossAccountIdFromObject: (obj: any): CrossAccountId => {
return addressToCrossAccountId(guessAddressAndExtractItNormalized(obj))
},
crossAccountIdFromObjectNormalized: (obj: any): CrossAccountId => {
return addressToCrossAccountId(guessAddressAndExtractItNormalized(obj))
},
}
export const mirror = {
substrateToEthereum: addressToEvm,
ethereumToSubstrate: evmToAddress,
}
export const normalize = {
substrateAddress: normalizeSubstrateAddress,
ethereumAddress: normalizeEthereumAddress,
}
export const compare = {
substrateAddresses: compareSubstrateAddresses,
ethereumAddresses: compareEthereumAddresses,
}
export const substrate = {
encode: encodeSubstrateAddress,
decode: decodeSubstrateAddress,
compare: compareSubstrateAddresses,
}
export const Address = {
constants,
is,
validate,
collection,
nesting,
to,
extract,
mirror,
normalize,
compare,
substrate,
algorithms,
StringUtils,
}