Owner Link
Overview
If you own both the parent and child collections and want to link assets between them, you can use the owner-link
operation type as shown below.
Asset link creation operation
An asset link creation operation within an ARTM typically consists of the following structure:
{
type: 'owner-link',
action: 'create',
args: [
// Operator
'equipWith_asmBrain',
// Opearand A: Boxer Asset ID
'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
// Opearand B: Brain Asset ID
'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21',
],
}
Ownership check for link creation
To create links, the sender of the transaction must be the owner of both assets' collections. Linking between assets owned on a Pass account and the Pass account owner's EOA is allowed. Links can also be created across chains as long as the ownership resolution is satisfied.
Usage
Create Link
import {
useGetARTM,
useSignAndSubmitTransaction,
useGetTransaction,
} from '@futureverse/asset-register-react/v2'
const linkOperation = {
type: 'owner-link',
action: 'create',
args: [
'equipWith_asmBrain',
// Boxer
'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
// Brain
'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21',
],
}
const LinkAccessory = ({ address }) => {
const {
artm,
reactQuery: { refetch: getARTM },
} = useGetARTM(
{
address,
[],
},
{ enabled: false },
)
const { submitAsync, transaction } = useSignAndSubmitTransaction()
// Polling tx status after submitted
const { transaction: transactionStatus } = useGetTransaction(
{ transactionHash: transaction?.transactionHash as any },
{
refetchInterval: (data) => (data?.status === 'PENDING' ? 2000 : false),
enabled: !!transaction?.transactionHash,
},
)
const submitARTM = async () => {
const { data: artm } = await getARTM()
if (!artm) {
return
}
artm.addOperation(linkOperation)
return submitAsync({ artm })
}
return (
<>
<button onClick={submitARTM}>Submit link accessory TX</button>
{transactionStatus && <div>{`tx status: ${transactionStatus.status}`}</div>}
</>
)
}
import { AssetRegister } from '@futureverse/asset-register'
import {
AssetTransactionMessage,
Signature,
chainAddressFromString,
} from '@futureverse/asset-register/types'
import { ARTM, STATEMENTS } from '@futureverse/artm'
const address = "YOUR_WALLET_ADDRESS"
const linkOperation = {
type: 'owner-link',
action: 'create',
args: [
'equipWith_asmBrain',
'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21',
],
}
const ar = new AssetRegister({
...
})
const getARTM = async () => {
const nonce = await ar.nonceForChainAddress(chainAddressFromString(address))
return new ARTM({
operations: [linkOperation],
nonce,
address,
statement: STATEMENTS.ASSET_UPDATE,
})
}
const signAndSubmit = async () => {
const artm = await getARTM()
await ar.sign(artm)
const assetInput = {
transaction: artm.message as AssetTransactionMessage,
signature: artm.signature as Signature,
}
return ar.submitTransaction(assetInput)
}
signAndSubmit()
Get nonce.
query GetNonceForChainAddress($input: NonceInput!) { getNonceForChainAddress(input: $input) }
{ "input": { "chainAddress": "0x2d2438c6281b5115733287fc279f854c868d3ee2" } }
Get message and signature through ARTM.
import { ARTM, STATEMENTS } from '@futureverse/artm' const linkOperation = { type: 'owner-link', action: 'create', args: [ 'equipWith_asmBrain', 'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000', 'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21', ], } const artm = new ARTM({ operations: [linkOperation], nonce, address, statement: STATEMENTS.ASSET_UPDATE, })
Submit transaction
mutation SubmitTransaction($input: SubmitTransactionInput!) { submitTransaction(input: $input) { transactionHash } }
{ "input": { "transaction": artm.message, "signature": artm.signature } }
Check transaction status
query GetTransaction($transactionHash: TransactionHash!) { transaction(transactionHash: $transactionHash) { id status transactionHash error { message code } } }
{ "transactionHash": "0x0f35cc253abccfb69ecfba5a3fc6696a518aa5ad8bc1e19c71c73446269057c8" }
Delete Link
import {
useGetARTM,
useSignAndSubmitTransaction,
useGetTransaction,
} from '@futureverse/asset-register-react/v2'
const linkOperation = {
type: 'owner-link',
action: 'delete',
args: [
'equipWith_asmBrain',
// Boxer
'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
// Brain
'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21',
],
}
const LinkAccessory = ({ address }) => {
const {
artm,
reactQuery: { refetch: getARTM },
} = useGetARTM(
{
address,
[],
},
{ enabled: false },
)
const { submitAsync, transaction } = useSignAndSubmitTransaction()
// Polling tx status after submitted
const { transaction: transactionStatus } = useGetTransaction(
{ transactionHash: transaction?.transactionHash as any },
{
refetchInterval: (data) => (data?.status === 'PENDING' ? 2000 : false),
enabled: !!transaction?.transactionHash,
},
)
const submitARTM = async () => {
const { data: artm } = await getARTM()
if (!artm) {
return
}
artm.addOperation(linkOperation)
return submitAsync({ artm })
}
return (
<>
<button onClick={submitARTM}>Submit link accessory TX</button>
{transactionStatus && <div>{`tx status: ${transactionStatus.status}`}</div>}
</>
)
}
import { AssetRegister } from '@futureverse/asset-register'
import {
AssetTransactionMessage,
Signature,
chainAddressFromString,
} from '@futureverse/asset-register/types'
import { ARTM, STATEMENTS } from '@futureverse/artm'
const address = "YOUR_WALLET_ADDRESS"
const linkOperation = {
type: 'owner-link',
action: 'delete',
args: [
'equipWith_asmBrain',
'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21',
],
}
const ar = new AssetRegister({
...
})
const getARTM = async () => {
const nonce = await ar.nonceForChainAddress(chainAddressFromString(address))
return new ARTM({
operations: [linkOperation],
nonce,
address,
statement: STATEMENTS.ASSET_UPDATE,
})
}
const signAndSubmit = async () => {
const artm = await getARTM()
await ar.sign(artm)
const assetInput = {
transaction: artm.message as AssetTransactionMessage,
signature: artm.signature as Signature,
}
return ar.submitTransaction(assetInput)
}
signAndSubmit()
Get nonce.
query GetNonceForChainAddress($input: NonceInput!) { getNonceForChainAddress(input: $input) }
{ "input": { "chainAddress": "0x2d2438c6281b5115733287fc279f854c868d3ee2" } }
Get message and signature through ARTM.
import { ARTM, STATEMENTS } from '@futureverse/artm' const linkOperation = { type: 'owner-link', action: 'delete', args: [ 'equipWith_asmBrain', 'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000', 'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21', ], } const artm = new ARTM({ operations: [linkOperation], nonce, address, statement: STATEMENTS.ASSET_UPDATE, })
Submit transaction
mutation SubmitTransaction($input: SubmitTransactionInput!) { submitTransaction(input: $input) { transactionHash } }
{ "input": { "transaction": artm.message, "signature": artm.signature } }
Check transaction status
query GetTransaction($transactionHash: TransactionHash!) { transaction(transactionHash: $transactionHash) { id status transactionHash error { message code } } }
{ "transactionHash": "0x0f35cc253abccfb69ecfba5a3fc6696a518aa5ad8bc1e19c71c73446269057c8" }
Last updated