scrypt-ord
is the official sCrypt 1Sat Ordinals SDK. With it, you can effortlessly develop smart contracts integrated with 1Sat Ordinals, covering both non-fungible tokens (NFTs) and fungible tokens (FTs).
npm i scrypt-ord
OrdiProvider
When you use sCrypt 1Sat Ordinals SDK, we recommend that you use OrdiProvider
to create Signer
. This allows your transactions to be indexed faster.
export function getDefaultSigner(): TestWallet {
return new TestWallet(
myPrivateKey,
new OrdiProvider(bsv.Networks.mainnet)
)
}
To lock a 1sat
NFT via a smart contract, have your smart contract extend the OrdinalNFT
class:
import { method, prop, assert, ByteString, sha256, Sha256 } from "scrypt-ts";
import { OrdinalNFT } from "scrypt-ord";
export class HashLockNFT extends OrdinalNFT {
@prop()
hash: Sha256;
constructor(hash: Sha256) {
super();
// Important: Call `init` after the `super()` statement.
this.init(...arguments);
this.hash = hash;
}
@method()
public unlock(message: ByteString) {
assert(this.hash === sha256(message), "hashes are not equal");
}
}
To inscribe an NFT within a contract:
HashLockNFT.loadArtifact();
const text = "Hello sCrypt and 1Sat Ordinals";
const message = toByteString(text, true);
const hash = sha256(message);
const instance = new HashLockNFT(hash);
await instance.connect(getDefaultSigner());
const inscriptionTx = await instance.inscribeText(text);
console.log("Inscribed NFT: ", inscriptionTx.id);
const recipientAddress = bsv.Address.fromString("your bitcoin address");
const { tx: transferTx } = await instance.methods.unlock(message, {
transfer: new OrdiNFTP2PKH(Addr(recipientAddress.toByteString())),
});
console.log("Transferred NFT: ", transferTx.id);
const inscriptionTx = await instance.inscribeText("hello world!");
console.log("Inscribed NFT: ", inscriptionTx.id);
const bb = readFileSync(join(__dirname, "..", "..", "logo.png")).toString(
"base64"
);
const tx = await instance.inscribeImage(bb, ContentType.PNG);
console.log("Inscribed NFT: ", tx.id);
const tx = await instance.inscribe({
content: `your content`,
contentType: `your contentType`,
});
console.log("Inscribed NFT: ", tx.id);
To transfer an existing NFT, typically secured by a P2PKH
lock, to a contract:
HashLockNFT.loadArtifact();
const text = "Hello sCrypt and 1Sat Ordinals";
const message = toByteString(text, true);
const hash = sha256(message);
const recipient = new HashLockNFT(hash);
await recipient.connect(getDefaultSigner());
// Create a P2PKH object from a UTXO
const p2pkh = OrdiNFTP2PKH.fromUTXO(`your UTXO`);
// Alternatively, create a P2PKH from an origin
const p2pkh = await OrdiNFTP2PKH.getLatestInstance(`origin TXID`);
await p2pkh.connect(getDefaultSigner());
const { tx: transferTx } = await p2pkh.methods.unlock(
(sigResps) => findSig(sigResps, `yourPubKey`),
PubKey(`yourPubKey`.toByteString()),
{
transfer: recipient,
pubKeyOrAddrToSign: `yourPubKey`,
} as OrdiMethodCallOptions<OrdiNFTP2PKH>
);
console.log("Transferred NFT: ", transferTx.id);
To transfer an NFT from one HashLockNFT
contract to another:
HashLockNFT.loadArtifact();
// Retrieve `HashLockNFT` instance holding the NFT
const nft = await HashLockNFT.getLatestInstance(`origin TXID`);
await nft.connect(getDefaultSigner());
const hash = sha256(toByteString("Hello sCrypt and 1Sat Ordinals", true));
const recipient = new HashLockNFT(hash);
await recipient.connect(getDefaultSigner());
// Send NFT to recipient
const { tx: transferTx } = await nft.methods.unlock(
toByteString(`unlock message`, true),
{
transfer: recipient,
}
);
console.log("Transferred NFT: ", transferTx.id);
HashLockFT.loadArtifact();
const tick = toByteString("DOGE", true);
const max = 100000n;
const lim = max / 10n;
const dec = 0;
const hashLock = new HashLockFT(
tick,
max,
lim,
dec,
sha256(toByteString("hello, sCrypt!:0", true))
);
await hashLock.connect(getDefaultSigner());
await hashLock.deployToken();
// Minting
const amt = 1000n;
const mintTx = await hashLock.mint(amt);
console.log("Minted tx: ", mintTx.id);
// Transfer
for (let i = 0; i < 3; i++) {
const receiver = new HashLockFT(
tick,
max,
lim,
dec,
sha256(toByteString(`hello, sCrypt!:${i + 1}`, true))
);
const recipients: Array<FTReceiver> = [
{
instance: receiver,
amt: 10n,
},
];
const { tx } = await hashLock.methods.unlock(
toByteString(`hello, sCrypt!:${i}`, true),
{
transfer: recipients,
}
);
hashLock = recipients[0].instance as HashLockFT;
console.log("Transfer tx: ", tx.id);
}
HashLockFT.loadArtifact();
const text = "Hello sCrypt and 1Sat Ordinals";
const message = toByteString(text, true);
const hash = sha256(message);
const recipient = new HashLockFT(hash);
// create p2pkh from a utxo
// NOTE: You can not use BSV20V1P2PKH.getLatestInstance for bsv20, it only works for NFT
const p2pkh = BSV20V1P2PKH.fromUTXO(`your utxo`);
await p2pkh.connect(getDefaultSigner());
const { tx: transferTx } = await p2pkh.methods.unlock(
(sigResps) => findSig(sigResps, `yourPubKey`),
PubKey(`yourPubKey`.toByteString()),
{
transfer: recipient,
pubKeyOrAddrToSign: `yourPubKey`,
} as OrdiMethodCallOptions<BSV20V1P2PKH>
);
console.log("Transferred FT: ", transferTx.id);
HashLockFT.loadArtifact();
const text = "Hello sCrypt and 1Sat Ordinals";
const message = toByteString(text, true);
const hash = sha256(message);
const recipient = new HashLockFT(hash);
// create p2pkh from a utxo
// NOTE: you can not use BSV20V1P2PKH.getLatestInstance for bsv20, it only works for NFT
const bsv20V1P2PKHs = await BSV20V1P2PKH.getBSV20(
"DOGE",
`your ordinal address`
);
await Promise.all(bsv20V1P2PKHs.map((p) => p.connect(signer)));
const recipients: Array<FTReceiver> = [
{
instance: new HashLockFT(tick, max, lim, dec, sha256(message)),
amt: 6n,
},
];
const { tx, nexts } = await BSV20V1P2PKH.transfer(
bsv20V1P2PKHs,
signer,
recipients
);
console.log("Transferred FT: ", transferTx.id);