Skip to main content

Tutorial 1: Inscribe Image

Overview

In this tutorial, we will use contract HashLock as an example to introduce how to inscribe an image on an ordinal, which is locked in a smart contract. It can be transferred by calling the contract.

note

Your wallet must be funded before inscribing the image.

First, you install scrypt-ord as an dependency in your project.

npm install scrypt-ord

Contract

The new contract HashLockNFT is almost the same as the previous implementation, except it must be derived from OrdinalNFT instead of SmartContract, which comes with package scrypt-ord.

class HashLockNFT extends OrdinalNFT {
...
}

It also stores a hash value in the contract. It will be unlocked successfully when calling the public method unlock with the correct hash preimage.

class HashLockNFT extends OrdinalNFT {
@prop()
hash: Sha256

...

@method()
public unlock(message: ByteString) {
assert(this.hash == sha256(message), 'hashes are not equal')
}
}

The base class OrdinalNFT encapsulates helper functions to handle ordinals. If you want to create your own contract that control Ordinal NFTs, you must derive from it.

Inscribe Image

We first create an instance of contract HashLockNFT. Next we call inscribeImage on the instance to inscribe an image.

// create contract instance
const message = toByteString('Hello sCrypt', true)
const hash = sha256(message)
const hashLock = new HashLockNFT(hash)
...
// inscribe image into contract
const image = readImage()
const mintTx = await hashLock.inscribeImage(image, 'image/png')

Execute command npx ts-node tests/examples/inscribeImage.ts to run this example.

Then you can check your inscription on a block explorer.

Click Decode.

Now that the inscription is locked to a contract instance, it is controlled by the smart contract, which means it can only be transferred when the hash lock is unlocked.

This is different from using a P2PKH address to receive the inscription, where the inscription is controlled by a private key.

Transfer the Inscription

The contract instance holds the inscription and we transfer it to a bitcoin address.

Step 1. Create Receiver Instance

Class OrdiNFTP2PKH represents an address that can hold inscriptions. Its constructor takes one parameter which is the receiving address.

const receiver = new OrdiNFTP2PKH(Addr(address.toByteString()))

Step 2. Call the Contract

Similar to contract calling before, we call the unlock of HashLockNFT as follows.

const { tx: transferTx } = await hashLock.methods.unlock(
message,
{
transfer: receiver, // <-----
} as OrdiMethodCallOptions<HashLockNFT>
)

We pass the receiver instance to transfer of struct OrdiMethodCallOptions.

Conclusion

Great! You have finished the tutorial on how to inscribe and transfer a 1Sat Ordinal with a smart contract.

The full complete contract and example can be found in sCrypt's repository.