npm package: @futureverse/artm
Description: Asset Register Transaction Message (ARTM) describes the standard approach for parsing updates to the off-chain Asset Register database. One ARTM can describe multiple sequential operations on the Asset Register. A ZK-rollup of these transactions will be p
Latest version: 2.3.2

# ARTM

Asset Register Transaction Message (ARTM) describes the standard approach for parsing updates to the off-chain Asset Register database. One ARTM can describe multiple sequential operations on the Asset Register. A ZK-rollup of these transactions will be pushed to The Root Network to validate the updates made to the Asset Register periodically.

## Quick start

### Create an ARTM with a single operation

```ts
const artm = new ARTM({
  statement: 'An update is being made to your inventory',
  operations: [
    {
      type: 'asset-link',
      action: 'create',
      args: [
        'equipWith_asmBrain',
        'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
        'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21',
      ],
    },
  ],
  address: '0x6bca6de2dbdc4e0d41f7273011785ea16ba47182',
  nonce: 0,
})

console.log(artm.statement) // An update is being made to your inventory
console.log(artm.address) // 0x6bca6de2dbdc4e0d41f7273011785ea16ba47182
console.log(artm.nonce) // 0
console.log(artm.operations) // [ { type: 'asset-link', action: 'create', args: [Array] } ]
```

### Create an ARTM and add multiple operations

```ts
const artm = new ARTM({
  address: '0x6bca6de2dbdc4e0d41f7273011785ea16ba47182',
  nonce: 0,
})
  .addOperation({
    type: 'asset-link',
    action: 'delete',
    args: [
      'equipWith_asmBrain',
      'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
      'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:20',
    ],
  })
  .addOperation({
    type: 'asset-link',
    action: 'create',
    args: [
      'equipWith_asmBrain',
      'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
      'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21',
    ],
  })

console.log(artm.operations.length) // 2
```

### Add a signature to an ARTM

```ts
const artm = new ARTM({
  operations: [
    {
      type: 'asset-link',
      action: 'create',
      args: [
        'equipWith_asmBrain',
        'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
        'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21',
      ],
    },
  ],
  address: '0xaebC048B4D219D6822C17F1fe06E36Eba67D4144',
  nonce: 0,
}).setSignature(
  '0xe3c7ca6fb3a93e0b043f5653d1b0e95cf9976b97d6efc25a4d1cbcba008d2e2724cdb2a0273518ab719705bbdeebc228eda25c4ad2b01b70addb29bd132235481c',
)

console.log(await artm.verify()) // true
```

### Now all together

```ts
const artm = new ARTM({
  address: '0xaebC048B4D219D6822C17F1fe06E36Eba67D4144',
  nonce: 0,
})
  .addOperation({
    type: 'asset-link',
    action: 'create',
    args: [
      'equipWith_asmBrain',
      'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000',
      'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21',
    ],
  })
  .setSignature(
    '0xe3c7ca6fb3a93e0b043f5653d1b0e95cf9976b97d6efc25a4d1cbcba008d2e2724cdb2a0273518ab719705bbdeebc228eda25c4ad2b01b70addb29bd132235481c',
  )

console.log(await artm.verify()) // true
```

## Motivation

When making updates to the Asset Register there needs to be a clearly defined transaction message standard that will be followed and can be used to reliably prove updates. This RFC takes inspiration from [ERC-4361: Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361).

## Specification

Asset Register Transaction Message generation works as follows:

1. A list of asset register updates is first defined
2. A message is created that starts with `\x19Ethereum Signed Message:\n<length of message>` as defined in [ERC-191](https://eips.ethereum.org/EIPS/eip-191)
3. Each asset register update will then be defined sequentially in the order the updates should take place.
4. The end of the message will have the address making the updates and the nonce.
5. Sign message using the correct wallet
6. Submit transaction to Asset Register

### Transaction Hash

A transaction hash is generated based on the message + signature

```ts
keccak256(message + signature)
```

If the signature is `null` then the transaction hash will also be `null`

### Example Message

```markdown
Asset Register transaction

An update is being made to your inventory

Operations:

asset-link delete

- equipWith_asmBrain
- did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000
- did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:20
  end

asset-link create

- equipWith_asmBrain
- did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000
- did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21
  end

asset-link create

- equipWith_gloves
- did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000
- did:fv-asset:1:root:0x1ea66a857de297471bc12dd12d93853ff6617284:21
  end

ownership update

- did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000
  end

asset-link create

- equipwith_hairStyle
- did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000
- did:fv-asset:off-chain:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1234
  end

Operations END

Address: 0x854A3E045Ac44a7f4A1726AdAC576029135DFdA7
Nonce:1
```

### Informal Message Template

A Bash-like informal template of the full message is presented below for readability and ease of understanding. Field descriptions are provided in the following section.

```bash
Asset Register transaction

${statement}

Operations:
${operations[0]["type"]} ${operations[0]["action"]}
- ${operations[0]["args"][0]} - ${operations[0]["args"][1]}
...
- ${operations[0]["args"][n]}

${operations[1]["type"]} ${operations[1]["action"]}
- ${operations[1]["args"][0]}
- ${operations[1]["args"][1]}
...
- ${operations[1]["args"][n]}
end

...

${operations[n]["type"]} ${operations[n]["action"]}
- ${operations[n]["args"][0]}
- ${operations[n]["args"][1]}
...
- ${operations[n]["args"][n]}
end

Operations END

Address: ${address}
Nonce: ${nonce}
```

#### Message Field Descriptions

| Field      | Description                                                                                                                                                       |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| statement  | (optional) is a human-readable ASCII assertion that the user will sign, and it must not contain '\n' (the byte 0x0a).                                             |
| nonce      | an incremented number for each address that is kept track of by the Asset Register to mitigate replay attacks.                                                    |
| address    | is the Ethereum address performing the signing conformant to capitalization encoded checksum specified in https://eips.ethereum.org/EIPS/eip-55 where applicable? |
| operations | an array of updated objects with type, action and args                                                                                                            |

### ABNF

The `message` MUST conform with the following Augmented Backus–Naur Form (ABNF, RFC 5234) expression (note that `%s` denotes case sensitivity for a string term, as per RFC 7405).

```abnf
artm =
  %s"Asset Register transaction" LF
  LF
  [ statement LF ]
  LF
  %s"Operations:" LF
  LF
  operations
  %s"Operations END" LF
  LF
  %s"Address: " address LF
  %s"Nonce: " nonce

statement = 1*( reserved / unreserved / " " ) ; The purpose is to exclude LF (line breaks).

operations = *operation

operation = operation-type SP operation-action LF 1*(operation-argument) %s"end" 2*2LF

operation-type = *(ALPHA / "-")

operation-action = *(ALPHA / "-")

operation-argument = "-" SP *VCHAR LF

address = "0x" 40HEXDIG

nonce = 1*DIGIT

; ------------------------------------------------------------------------------
; RFC 3986

unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
reserved      = gen-delims / sub-delims
gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

; ------------------------------------------------------------------------------
; RFC 5234

ALPHA          =  %x41-5A / %x61-7A   ; A-Z / a-z
LF             =  %x0A ; linefeed
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
DIGIT = %x30-39 ; 0-9
SP = %x20 ; space
VCHAR =  %x21-7E ; visible (printing) characters

```

### Typescript Interface

```ts
interface ARTM {
  statement: string
  operations: {
    type: string
    action: string
    args: string[]
  }[]
  address: string
  nonce: number
  signature?: string
  transactionHash: string | null
  addSignature: () => void
  verify: () => boolean
}
```