Transactions
Modifications to asset links must be carried out via an Asset Register Transaction.
Submitting Transactions
Once you have created an ARTM and have signed it, you can submit it to the Asset Register
import { useAssetMutationMutation, useGetARTM } from '@futureverse/asset-registry-react/v2'
const Page = () => {
const { data: artm } = useGetARTM({
address: signer.address,
operations,
})
const { mutateAsync: submitTransactionAsync, data } = useSubmitTransaction()
const submitARTM = async () => {
// Sign transaction and set on the ARTM instance to validate signature
const signature = await signer.signMessage(artm.getMessageToSign())
artm.setSignature(signature)
// Submit transaction to Asset Registry API
submitTransactionAsync({
input: {
transaction: artm.message,
signature: artm.signature
}
})
}
return (
<button onClick={() => submitARTM()}>Submit ARTM</button>
)
}
import { AssetRegister } from '@futureverse/asset-register/v2'
import { ARTM, STATEMENTS } from '@futureverse/artm'
const ar = new AssetRegister({
...
})
//STEP 1: Get the nonce
const nonce = await ar.nonceForChainAddress(
walletAddress as ChainAddress,
).execute()[0]
//STEP 2: Create a message
const artmMessage = new ARTM({
address: walletAddress,
statement: STATEMENTS.OWNERSHIP,
nonce: nonce,
})
const operation = 'create'
artmMessage.operations = [
{
type: 'asset-link',
action: operation,
args: ['equipWith_asmBrain', boxerDid, asmGenTwoBrainDid],
},
]
// STEP 3: Sign the ARTM
const signature = await wallet.signMessage(artmMessage.getMessageToSign())
const input = {
signature: signature as Signature,
transaction: artmMessage.message as AssetTransactionMessage,
}
// STEP 4: Submit the transaction
const response = await ar.submitTransaction(input).execute()
GraphQL - Submit Transaction
mutation SubmitTransaction($input: SubmitTransactionInput!) {
submitTransaction(input: $input) {
transactionHash
}
}
{
"input": {
"transaction":"Asset Registry transaction\n\nAn update is being made to your inventory\n\nOperations:\n\nasset-link create\n- equipWith_asmBrain\n- did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000\n- did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21\nend\n\nOperations END\n\nAddress: 0x225b5333C2D8EC41F40D6463D44141786C2c4463\nNonce: 0",
"signature": "0x282dbd15e2ef7091c8599ce1073e7c0f94cd7a02526b6bc43b84f01f190b457047b34e0d3bb63797872dffa106f33f914d5e6ff6d2e978f39944c6af6efec7691b"
}
}
Example Response
{
"data": {
"submitTransaction": {
"transactionHash": "0x9aa26c9bfce628b160a43c155a12049c22c74276c28ca250df20df40f78baf1c"
}
}
}
Viewing transaction by hash
Once a transaction is submitted, you can view its status by querying it. Transaction information will live forever, making it available for future auditing purposes.
import { FC } from 'react'
import { useGetTransaction } from '@futureverse/asset-registry-react/v2'
import { TransactionHash } from '@futureverse/asset-registry/types'
type Props = {
transactionHash: string
}
export const TransactionStatus: FC<Props> = ({ transactionHash }) => {
const { transaction } = useGetTransaction(
{ transactionHash: transactionHash as TransactionHash },
{
refetchInterval: (data) => (data?.status === 'PENDING' ? 5000 : false),
},
)
if (!transaction) return null
return (
<div>
<h4>Transaction Status: </h4>
<pre>{JSON.stringify(transaction, undefined, 2)}</pre>
</div>
)
}
import { AssetRegister } from '@futureverse/asset-register/v2'
const ar = new AssetRegister({
...
})
const transactionStatus = await ar.transaction({
transactionHash: "0x91db1d71b775c42945055bbe21dc862bcc571c44b0a396bda3367040bcf4735e",
})
GraphQL - Transaction
query Transaction($transactionHash: TransactionHash!) {
transaction(transactionHash: $transactionHash) {
createdAt
events {
action
args
type
}
id
status
transactionHash
error {
message
code
}
}
}
{
"transactionHash": "0xe28a8c0d45eb432093a96f73f70802c6dd7c5047a9a710817233f6b4f1b96615"
}
{
"data": {
"transaction": {
"status": "SUCCESS",
"id": "VHJhbnNhY3Rpb246MHhlOThhOGMwZDQ1ZWI0MzIwOTNhOTZmNzNmNzA4MDJjNmRkN2M1MDQ3YTlhNzEwODE3MjMzZjZiNGYxYjk2NjE1",
"events": [
{
"action": "create",
"args": [
"equipWith_gloves",
"did:fv-asset:1:evm:0x59029213099dF720676bf0991a57e49518b00D72:1000",
"did:fv-asset:1:evm:0x2308742aa28cc460522ff855d24a365f99deba7b:23"
],
"type": "asset-link"
}
],
"transactionHash": "0xe28a8c0d45eb432093a96f73f70802c6dd7c5047a9a710817233f6b4f1b96615"
}
}
}
Viewing transactions by address
You can view all transactions initiated by an address.
import { useGetTransactions } from '@futureverse/asset-register-react/v2'
import { ChainAddress } from '@futureverse/asset-register/types'
export const Transactions = () => {
const { transactions } = useGetTransactions({
address: '0x2D2438C6281B5115733287fC279f854c868D3ee2' as ChainAddress,
})
if (!transactions) return null
return (
<div>
{transactions.map((tx) => (
<div key={tx.id}>
<div>{tx.transactionHash}</div>
<div>{tx.status}</div>
</div>
))}
</div>
)
}
import { AssetRegister } from '@futureverse/asset-register/v2'
const ar = new AssetRegister({
...
})
const transactionStatus = await ar.transactions({
address: '0x2D2438C6281B5115733287fC279f854c868D3ee2'
})
query GetTransactions($address: ChainAddress!, $first: Float) {
transactions(address: $address, first: $first) {
edges {
node {
createdAt
events {
action
args
type
}
id
status
transactionHash
error {
message
code
}
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}
{
"address": "0x2D2438C6281B5115733287fC279f854c868D3ee2",
"first": 2,
}
{
"data": {
"transactions": {
"edges": [
{
"node": {
"createdAt": 1715736913949,
"events": [
{
"action": "create",
"args": [
"equippedWith_accessoryEars",
"did:fv-asset:7672:root:303204:232",
"did:fv-asset:7672:root:240740:4"
],
"type": "asset-link"
},
{
"action": "delete",
"args": [
"equippedWith_accessoryEyewear",
"did:fv-asset:7672:root:303204:232",
"did:fv-asset:7672:root:245860:2"
],
"type": "asset-link"
}
],
"id": "VHJhbnNhY3Rpb246MHhiYTY2ZGZjNzQxOTIxNjllODRkMTQxYTQwYWJiZGJjMmE0ZWE5OTIwMGEyMjQwMzYyZjVjYTUzYmMzZjEyODBj",
"status": "SUCCESS",
"transactionHash": "0xba66dfc74192169e84d141a40abbdbc2a4ea99200a2240362f5ca53bc3f1280c",
"error": null
},
"cursor": "eyJjcmVhdGVkQXQiOjE3MTU3MzY5MTM5NDksImVvYSI6IjB4MmQyNDM4YzYyODFiNTExNTczMzI4N2ZjMjc5Zjg1NGM4NjhkM2VlMiIsInRyYW5zYWN0aW9uSGFzaCI6IjB4YmE2NmRmYzc0MTkyMTY5ZTg0ZDE0MWE0MGFiYmRiYzJhNGVhOTkyMDBhMjI0MDM2MmY1Y2E1M2JjM2YxMjgwYyJ9"
},
{
"node": {
"createdAt": 1714604822582,
"events": [
{
"action": "delete",
"args": [
"equippedWith_accessoryEars",
"did:fv-asset:7672:root:303204:232",
"did:fv-asset:7672:root:240740:4"
],
"type": "asset-link"
},
{
"action": "create",
"args": [
"equippedWith_accessoryEyewear",
"did:fv-asset:7672:root:303204:232",
"did:fv-asset:7672:root:245860:2"
],
"type": "asset-link"
}
],
"id": "VHJhbnNhY3Rpb246MHhmZTcyOWU5MGJhMWU2NGQzMzVkOWE0ZmE2NmEwODdiYWE5OTQzYWNiNGM3NmZiZGZkZTA2MDc0NTYxNDdjNGEz",
"status": "SUCCESS",
"transactionHash": "0xfe729e90ba1e64d335d9a4fa66a087baa9943acb4c76fbdfde0607456147c4a3",
"error": null
},
"cursor": "eyJjcmVhdGVkQXQiOjE3MTQ2MDQ4MjI1ODIsImVvYSI6IjB4MmQyNDM4YzYyODFiNTExNTczMzI4N2ZjMjc5Zjg1NGM4NjhkM2VlMiIsInRyYW5zYWN0aW9uSGFzaCI6IjB4ZmU3MjllOTBiYTFlNjRkMzM1ZDlhNGZhNjZhMDg3YmFhOTk0M2FjYjRjNzZmYmRmZGUwNjA3NDU2MTQ3YzRhMyJ9"
}
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "eyJjcmVhdGVkQXQiOjE3MTQ2MDQ4MjI1ODIsImVvYSI6IjB4MmQyNDM4YzYyODFiNTExNTczMzI4N2ZjMjc5Zjg1NGM4NjhkM2VlMiIsInRyYW5zYWN0aW9uSGFzaCI6IjB4ZmU3MjllOTBiYTFlNjRkMzM1ZDlhNGZhNjZhMDg3YmFhOTk0M2FjYjRjNzZmYmRmZGUwNjA3NDU2MTQ3YzRhMyJ9"
}
}
}
}
Last updated