Authentication
- Getting Started
- React
- API Reference
Transactions
- Overview
- Getting Started
- Usage
- Helper Functions
Assets
- Overview
- Getting Started
- Collectibles/NFTs
- Asset Register Transaction Message (ARTM)
- Swappables
- Tokens
- Asset Tree
- Error messages
Swappables
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
Copy
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 Register API
submitTransactionAsync({
input: {
transaction: artm.message,
signature: artm.signature
}
})
}
return (
<button onClick={() => submitARTM()}>Submit ARTM</button>
)
}
Copy
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 Register API
submitTransactionAsync({
input: {
transaction: artm.message,
signature: artm.signature
}
})
}
return (
<button onClick={() => submitARTM()}>Submit ARTM</button>
)
}
Copy
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
Copy
mutation SubmitTransaction($input: SubmitTransactionInput!) {
submitTransaction(input: $input) {
transactionHash
}
}
Copy
<pre class="language-json"><code class="lang-json">{
"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",
<strong> "signature": "0x282dbd15e2ef7091c8599ce1073e7c0f94cd7a02526b6bc43b84f01f190b457047b34e0d3bb63797872dffa106f33f914d5e6ff6d2e978f39944c6af6efec7691b"
</strong> }
}
</code></pre>
Example Response
Copy
{
"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.
Copy
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>
)
}
Copy
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>
)
}
Copy
import { AssetRegister } from '@futureverse/asset-register/v2'
const ar = new AssetRegister({
...
})
const transactionStatus = await ar.transaction({
transactionHash: "0x91db1d71b775c42945055bbe21dc862bcc571c44b0a396bda3367040bcf4735e",
})
GraphQL - Transaction
Copy
query Transaction($transactionHash: TransactionHash!) {
transaction(transactionHash: $transactionHash) {
createdAt
events {
action
args
type
}
id
status
transactionHash
error {
message
code
}
}
}
Copy
{
"transactionHash": "0xe28a8c0d45eb432093a96f73f70802c6dd7c5047a9a710817233f6b4f1b96615"
}
Copy
{
"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.
Copy
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>
)
}
Copy
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>
)
}
Copy
import { AssetRegister } from '@futureverse/asset-register/v2'
const ar = new AssetRegister({
...
})
const transactionStatus = await ar.transactions({
address: '0x2D2438C6281B5115733287fC279f854c868D3ee2'
})
Copy
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
}
}
}
Copy
{
"address": "0x2D2438C6281B5115733287fC279f854c868D3ee2",
"first": 2,
}
Copy
{
"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"
}
}
}
}
Was this page helpful?
Assistant
Responses are generated using AI and may contain mistakes.