From c5e38774e5d7961f24588c3e32368d40081d4a28 Mon Sep 17 00:00:00 2001 From: zhfnjust Date: Wed, 31 Jan 2024 12:27:12 +0000 Subject: [PATCH] Deploy website - based on 80b5a07f15fdaba7f2214f89d7c46b3b364588bb --- 404.html | 8 +++--- .../How to only sign p2pkh inputs/index.html | 17 +++++++++++ advanced/codeseparator/index.html | 10 +++---- advanced/how-to-add-a-provider/index.html | 10 +++---- advanced/how-to-add-a-signer/index.html | 10 +++---- .../how-to-build-an-oracle-service/index.html | 10 +++---- .../how-to-call-multiple-contracts/index.html | 10 +++---- .../how-to-debug-scriptcontext/index.html | 10 +++---- .../index.html | 10 +++---- advanced/how-to-replay-instance/index.html | 10 +++---- advanced/inline-asm/index.html | 10 +++---- advanced/sighash-type/index.html | 10 +++---- advanced/timeLock/index.html | 12 ++++---- ...close-f098212d4d8bfc7f2ae820ba5762125f.jpg | Bin 0 -> 11416 bytes assets/js/0480b142.50f49949.js | 1 - assets/js/0480b142.fc53a885.js | 1 + assets/js/558c5b2f.b771f7f8.js | 1 + assets/js/6eaa7f88.25e5cc9b.js | 1 - assets/js/6eaa7f88.2f89a807.js | 1 + assets/js/8c1b62a1.355a5c3f.js | 1 + assets/js/935f2afb.5566804d.js | 1 - assets/js/935f2afb.d8dc81eb.js | 1 + assets/js/b16c2f66.04979cd4.js | 1 - assets/js/b16c2f66.a78054bc.js | 1 + assets/js/e37cbbfc.72e97d56.js | 1 - assets/js/e37cbbfc.98321c60.js | 1 + assets/js/main.0d51a83c.js | 2 ++ ...CENSE.txt => main.0d51a83c.js.LICENSE.txt} | 0 assets/js/main.6c7efc8e.js | 2 -- assets/js/runtime~main.581029f8.js | 1 - assets/js/runtime~main.63c27662.js | 1 + bitcoin-basics/bsv/index.html | 10 +++---- bitcoin-basics/index.html | 10 +++---- category/advanced/index.html | 10 +++---- category/tutorials-1/index.html | 10 +++---- category/tutorials/index.html | 10 +++---- ethereum-devs/index.html | 10 +++---- faq/index.html | 10 +++---- how-to-debug-a-contract/index.html | 10 +++---- .../call-deployed/index.html | 10 +++---- .../deploy-cli/index.html | 10 +++---- .../faucet/index.html | 10 +++---- .../how-to-customize-a-contract-tx/index.html | 10 +++---- how-to-deploy-and-call-a-contract/index.html | 10 +++---- .../how-to-integrate-dotwallet/index.html | 10 +++---- how-to-integrate-a-frontend/index.html | 10 +++---- how-to-publish-a-contract/index.html | 10 +++---- how-to-test-a-contract/index.html | 10 +++---- how-to-verify-a-contract/index.html | 10 +++---- how-to-write-a-contract/built-ins/index.html | 10 +++---- how-to-write-a-contract/index.html | 10 +++---- .../scriptcontext/index.html | 10 +++---- .../stateful-contract/index.html | 10 +++---- img/close.jpg | Bin 0 -> 11416 bytes img/outpoint.webp | Bin 0 -> 8728 bytes index.html | 10 +++---- installation/index.html | 10 +++---- overview/index.html | 8 +++--- reference/classes/ActionError/index.html | 10 +++---- reference/classes/BsvApi/index.html | 10 +++---- reference/classes/Constants/index.html | 10 +++---- reference/classes/ContractApi/index.html | 10 +++---- reference/classes/DefaultProvider/index.html | 10 +++---- reference/classes/DotwalletSigner/index.html | 10 +++---- reference/classes/DummyProvider/index.html | 10 +++---- reference/classes/FunctionCall/index.html | 10 +++---- .../classes/GorillapoolProvider/index.html | 10 +++---- reference/classes/HashedMap/index.html | 10 +++---- reference/classes/HashedSet/index.html | 10 +++---- reference/classes/OpCode/index.html | 10 +++---- reference/classes/Provider/index.html | 10 +++---- reference/classes/ScryptProvider/index.html | 10 +++---- reference/classes/SensibleProvider/index.html | 10 +++---- reference/classes/SensiletSigner/index.html | 10 +++---- reference/classes/SigHash/index.html | 10 +++---- reference/classes/Signer/index.html | 10 +++---- reference/classes/SmartContract/index.html | 10 +++---- reference/classes/SmartContractLib/index.html | 10 +++---- reference/classes/TAALSigner/index.html | 10 +++---- reference/classes/TaalProvider/index.html | 10 +++---- reference/classes/TestWallet/index.html | 10 +++---- reference/classes/Utils/index.html | 10 +++---- reference/classes/VarIntReader/index.html | 10 +++---- reference/classes/VarIntWriter/index.html | 10 +++---- .../classes/WhatsonchainProvider/index.html | 10 +++---- reference/classes/bsv.Address/index.html | 10 +++---- reference/classes/bsv.Block/index.html | 10 +++---- reference/classes/bsv.BlockHeader/index.html | 10 +++---- reference/classes/bsv.ECIES/index.html | 10 +++---- reference/classes/bsv.HDPrivateKey/index.html | 10 +++---- reference/classes/bsv.HDPublicKey/index.html | 10 +++---- reference/classes/bsv.MerkleBlock/index.html | 10 +++---- reference/classes/bsv.Message/index.html | 10 +++---- reference/classes/bsv.Mnemonic/index.html | 10 +++---- reference/classes/bsv.Opcode/index.html | 10 +++---- reference/classes/bsv.PrivateKey/index.html | 10 +++---- reference/classes/bsv.PublicKey/index.html | 10 +++---- reference/classes/bsv.Script-1/index.html | 10 +++---- .../bsv.Script.Interpreter-1/index.html | 10 +++---- .../classes/bsv.Transaction-1/index.html | 10 +++---- .../bsv.Transaction.Input-1/index.html | 10 +++---- .../index.html | 10 +++---- .../classes/bsv.Transaction.Output/index.html | 10 +++---- .../bsv.Transaction.Signature/index.html | 10 +++---- .../bsv.Transaction.UnspentOutput/index.html | 10 +++---- reference/classes/bsv.Unit/index.html | 10 +++---- reference/classes/bsv.crypto.BN/index.html | 10 +++---- reference/classes/bsv.crypto.Point/index.html | 10 +++---- .../classes/bsv.crypto.Signature/index.html | 10 +++---- .../classes/bsv.encoding.Base58/index.html | 10 +++---- .../bsv.encoding.Base58Check/index.html | 10 +++---- .../bsv.encoding.BufferReader/index.html | 10 +++---- .../bsv.encoding.BufferWriter/index.html | 10 +++---- .../classes/bsv.encoding.Varint/index.html | 10 +++---- reference/enums/ProviderEvent/index.html | 10 +++---- reference/enums/SignatureHashType/index.html | 10 +++---- reference/index.html | 10 +++---- reference/interfaces/Artifact/index.html | 10 +++---- .../interfaces/ContractCalledEvent/index.html | 10 +++---- .../interfaces/ContractTransaction/index.html | 10 +++---- .../DefaultProviderOption/index.html | 10 +++---- reference/interfaces/LogConfig/index.html | 10 +++---- .../interfaces/MethodCallOptions/index.html | 10 +++---- .../interfaces/MethodCallTxBuilder/index.html | 10 +++---- .../MultiContractCallOptions/index.html | 10 +++---- .../MultiContractTransaction/index.html | 10 +++---- reference/interfaces/Outpoint/index.html | 10 +++---- reference/interfaces/RequestConfig/index.html | 10 +++---- reference/interfaces/ScriptContext/index.html | 10 +++---- reference/interfaces/ScryptConfig/index.html | 10 +++---- .../SignTransactionOptions/index.html | 10 +++---- .../interfaces/SignatureRequest/index.html | 10 +++---- .../interfaces/SignatureResponse/index.html | 10 +++---- reference/interfaces/StatefulNext/index.html | 10 +++---- reference/interfaces/SubScription/index.html | 10 +++---- .../interfaces/SubscribeOptions/index.html | 10 +++---- .../interfaces/TransactionResponse/index.html | 10 +++---- reference/interfaces/TxContext/index.html | 10 +++---- reference/interfaces/TxInputRef/index.html | 10 +++---- reference/interfaces/TxOutputRef/index.html | 10 +++---- .../interfaces/UtxoQueryOptions/index.html | 10 +++---- reference/interfaces/VerifyResult/index.html | 10 +++---- .../bsv.Networks.Network/index.html | 10 +++---- .../interfaces/bsv.Script.IOpChunk/index.html | 10 +++---- .../index.html | 10 +++---- .../bsv.Transaction.IUnspentOutput/index.html | 10 +++---- reference/interfaces/bsv.Util/index.html | 10 +++---- .../interfaces/bsv.crypto.IOpts/index.html | 10 +++---- reference/modules/bsv.Networks/index.html | 10 +++---- .../modules/bsv.Script.Interpreter/index.html | 10 +++---- reference/modules/bsv.Script/index.html | 10 +++---- .../modules/bsv.Transaction.Input/index.html | 10 +++---- .../bsv.Transaction.Sighash/index.html | 10 +++---- reference/modules/bsv.Transaction/index.html | 10 +++---- reference/modules/bsv.crypto.ECDSA/index.html | 10 +++---- reference/modules/bsv.crypto.Hash/index.html | 10 +++---- .../modules/bsv.crypto.Random/index.html | 10 +++---- reference/modules/bsv.crypto/index.html | 10 +++---- reference/modules/bsv.encoding/index.html | 10 +++---- reference/modules/bsv/index.html | 10 +++---- search/index.html | 8 +++--- sitemap.xml | 2 +- tokens/ft/existing/index.html | 10 +++---- tokens/ft/index.html | 10 +++---- tokens/ft/multiple/index.html | 10 +++---- tokens/ft/woc-bsv20-plugin/index.html | 10 +++---- tokens/index.html | 10 +++---- tokens/nft/existing/index.html | 10 +++---- tokens/nft/index.html | 10 +++---- tokens/tutorials/inscribe-image/index.html | 10 +++---- tokens/tutorials/mint-bsv20-v1/index.html | 10 +++---- tokens/tutorials/mint-bsv20-v2/index.html | 10 +++---- tokens/tutorials/ordinal-lock/index.html | 10 +++---- tutorials/auction/index.html | 10 +++---- tutorials/escrow/index.html | 10 +++---- tutorials/hello-world/index.html | 10 +++---- tutorials/oracle/index.html | 10 +++---- tutorials/ordinal-auction/index.html | 27 ++++++++++++++++++ tutorials/tic-tac-toe/index.html | 10 +++---- tutorials/voting/index.html | 10 +++---- tutorials/zkp/index.html | 10 +++---- 181 files changed, 843 insertions(+), 797 deletions(-) create mode 100644 advanced/How to only sign p2pkh inputs/index.html create mode 100644 assets/images/close-f098212d4d8bfc7f2ae820ba5762125f.jpg delete mode 100644 assets/js/0480b142.50f49949.js create mode 100644 assets/js/0480b142.fc53a885.js create mode 100644 assets/js/558c5b2f.b771f7f8.js delete mode 100644 assets/js/6eaa7f88.25e5cc9b.js create mode 100644 assets/js/6eaa7f88.2f89a807.js create mode 100644 assets/js/8c1b62a1.355a5c3f.js delete mode 100644 assets/js/935f2afb.5566804d.js create mode 100644 assets/js/935f2afb.d8dc81eb.js delete mode 100644 assets/js/b16c2f66.04979cd4.js create mode 100644 assets/js/b16c2f66.a78054bc.js delete mode 100644 assets/js/e37cbbfc.72e97d56.js create mode 100644 assets/js/e37cbbfc.98321c60.js create mode 100644 assets/js/main.0d51a83c.js rename assets/js/{main.6c7efc8e.js.LICENSE.txt => main.0d51a83c.js.LICENSE.txt} (100%) delete mode 100644 assets/js/main.6c7efc8e.js delete mode 100644 assets/js/runtime~main.581029f8.js create mode 100644 assets/js/runtime~main.63c27662.js create mode 100644 img/close.jpg create mode 100644 img/outpoint.webp create mode 100644 tutorials/ordinal-auction/index.html diff --git a/404.html b/404.html index f381bfc24..5b6f444b4 100644 --- a/404.html +++ b/404.html @@ -4,13 +4,13 @@ Page Not Found | sCrypt - - + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- - + + \ No newline at end of file diff --git a/advanced/How to only sign p2pkh inputs/index.html b/advanced/How to only sign p2pkh inputs/index.html new file mode 100644 index 000000000..1df0c504c --- /dev/null +++ b/advanced/How to only sign p2pkh inputs/index.html @@ -0,0 +1,17 @@ + + + + + +How to Sign P2PKH Inputs Using the Signer Class | sCrypt + + + + +
+
Skip to main content

How to Sign P2PKH Inputs Using the Signer Class

In certain scenarios, it is necessary to sign only P2PKH inputs when working with transactions in sCrypt. This documentation will guide you through the process of utilizing the Signer class to achieve this.

Prerequisites

Before proceeding, make sure you have a basic understanding of the sCrypt. library and have set up the required dependencies.

Implementation

1. Initialize a UTXO for P2PKH

Start by defining a P2PKH Unspent Transaction Output (UTXO) that you intend to use for your transaction:

const utxo = {
txId: '5260b12348608a33c2ac90ed8a08e0b3eb90bbe862bcea6b21b1f29f1c2fdee0',
outputIndex: 0,
script: bsv.Script.fromASM('OP_DUP OP_HASH160 af838fed6517e595e6761c2b96849bec473b00f8 OP_EQUALVERIFY OP_CHECKSIG').toHex(),
satoshis: 1000,
};

2. Add the P2PKH UTXO to the Transaction

Use the from() method to add the P2PKH UTXO to your transaction. This marks the input as a P2PKH input:

tx.from(utxo);

3. Verify Input Script Before Signing

Before signing the transaction, ensure that the input script is empty. This can be done with the following code:

console.log(tx.inputs[2].script.toASM()); // Empty, no signature

4. Sign the Transaction

Use the Signer class to sign the transaction:

const signer = getDefaultSigner();
await signer.signTransaction(tx);

5. Verify Input Script After Signing

After signing, confirm that the input script now contains the signature and public key:

console.log(tx.inputs[2].script.toASM()); // Should contain signature and pubkey

Example Implementation

Here is a simplified example demonstrating the steps above within a transaction :

const tx = new bsv.Transaction();
// Add inputs, outputs, and other transaction details as needed

// Add P2PKH UTXO
tx.from(utxo);

// Verify input script before signing
console.log(tx.inputs[2].script.toASM()); // Empty, no signature

// Sign the transaction
const signer = getDefaultSigner();
await signer.signTransaction(tx);

// Verify input script after signing
console.log(tx.inputs[2].script.toASM()); // Should contain signature and pubkey

.................................
.................................

// Finalize the transaction
const finalizedTx = tx.build();

Conclusion

By following these steps, your transaction sign only P2PKH inputs using the Signer class in sCrypt. If you encounter any issues or have specific requirements, +please refer to the sCrypt slack channel to seek further assistance.

+ + + + \ No newline at end of file diff --git a/advanced/codeseparator/index.html b/advanced/codeseparator/index.html index 14e1dbb47..e03ea3cd4 100644 --- a/advanced/codeseparator/index.html +++ b/advanced/codeseparator/index.html @@ -4,17 +4,17 @@ Use Code Separators | sCrypt - - + +
-
Skip to main content

Use Code Separators

How Code Separators Work

In a Bitcoin signature, what is signed is serialized ScriptContext, whose format is as follows: +

Use Code Separators

How Code Separators Work

In a Bitcoin signature, what is signed is serialized ScriptContext, whose format is as follows:

Part 5, scriptCode, usually contains the entire smart contract, i.e., locking script. The only exception is when there is OP_CODESEPARATOR (OCS) in it. When the signature is being verified by checkSig, scriptCode is the locking script but removing everything up to and including the last executed OCS.

If multiple instances of OP_CODESEPARATOR are present, a subsequent checkSig will only use the part of the locking script after the most recent occurrence of OP_CODESEPARATOR as the scriptCode.

How to Insert Code Separators

To insert an OP_CODESEPARATOR in place, simply invoke insertCodeSeparator().

export class CodeSeparator extends SmartContract {

@prop()
readonly addresses: FixedArray<Addr, 3>;

constructor(addresses: FixedArray<Addr, 3>) {
super(...arguments);
this.addresses = addresses;
}

@method()
public unlock(sigs: FixedArray<Sig, 3>, pubKeys: FixedArray<PubKey, 3>) {
assert(pubKey2Addr(pubKeys[0]) == this.addresses[0]);
this.insertCodeSeparator()
assert(this.checkSig(sigs[0], pubKeys[0]));

this.insertCodeSeparator()
assert(pubKey2Addr(pubKeys[1]) == this.addresses[1]);
assert(this.checkSig(sigs[1], pubKeys[1]));

this.insertCodeSeparator()
assert(pubKey2Addr(pubKeys[2]) == this.addresses[2]);
assert(this.checkSig(sigs[2], pubKeys[2]));
}

}

In the above example, the unlock method calls insertCodeSeparator. Each invocation of checkSig will use the code below the most recent invocation of insertCodeSeparator in the signature verification process. Multiple OP_CODESEPARATORs can be inserted, each affecting the checkSig right after it.

Generate a Signature

When OP_CODESEPARATOR is used, we need to change the way to get signatures. This is because conventionally, the signature covers the entire locking script, instead of a subscript with everything before OCS removed. We can achieve this by passing the index of insertCodeSeparator as a method call parameter, to specify which OP_CODESEPARATOR divides the locking script. Let's take a look at an example for the smart contract above:

// Create array of signature options, each for a separate public key.
const pubKeyOrAddrToSign: SignaturesOption = []
for (let i = 0; i < publicKeys.length; i++) {
const pubKey = publicKeys[i]
pubKeyOrAddrToSign.push({
pubKeyOrAddr: pubKey, // The public key for which a signature will be created.
csIdx: i // Index of the `insertCodeSeparator` call, starting from 0
// I.e., if csIdx = 1, then only the code starting from and including
// the second occurence of `insertCodeSeparator` will be signed.
})
}
const callContract = async () => await demo.methods.unlock(
(sigResps) => {
// Inside the signature responses we can observe,
// which instance of the `insertCodeSeparator` the signature
// takes into account:
console.log(sigResps)
return findSigs(sigResps, publicKeys)
},
publicKeys.map((publicKey) => PubKey(toHex(publicKey))) as FixedArray<PubKey, 3>,
{
pubKeyOrAddrToSign
} as MethodCallOptions<CodeSeparator>
)
expect(callContract()).not.throw
- - + + \ No newline at end of file diff --git a/advanced/how-to-add-a-provider/index.html b/advanced/how-to-add-a-provider/index.html index bebe04521..26b11f477 100644 --- a/advanced/how-to-add-a-provider/index.html +++ b/advanced/how-to-add-a-provider/index.html @@ -4,13 +4,13 @@ How to Add a Provider | sCrypt - - + +
-

How to Add a Provider

In the contract testing section, we learned about the Provider class in sCrypt. This class serves as an abstraction of a Bitcoin node, allowing your application to communicate with the Bitcoin network.

sCrypt provides the following providers by default:

  • DummyProvider: A mockup provider intended for local testing. It does not connect to the Bitcoin blockchain and thus cannot send transactions.

  • DefaultProvider: The default provider is the safest and easiest way to begin developing on Bitcoin, and is also robust enough for use in production. It can be used in testnet as well as mainnet.

  • For a full list of providers, see here.

Implementation

Base Class Provider

To implement your own provider, you must extend the base class Provider. Here's the definition of this class:

/**
* A Provider is an abstraction of non-account-based operations on a blockchain and is generally not directly involved in signing transaction or data.
*/
export abstract class Provider extends EventEmitter {

constructor() {
super()
this._isProvider = true;
}

/**
* check if provider is ready
*/
abstract isConnected(): boolean;

/**
* Implement the connection provider, for example, verify the api key during the connection process.
* @returns a connected provider. Throw an exception if the connection fails.
*/
abstract connect(): Promise<this>;

/**
* update provider network
* @param network Network type to be updated
*/
abstract updateNetwork(network: bsv.Networks.Network): Promise<boolean>;

/**
* @returns The network this provider is connected to.
*/
abstract getNetwork(): Promise<bsv.Networks.Network>;

/**
* @returns The fee rate for sending transactions through this provider.
*/
abstract getFeePerKb(): Promise<number>;

/**
* Get a best guess of the fee for a transaction.
* @param tx A transaction object to estimate.
* @returns The estimated fee in satoshis.
*/
async getEstimateFee(tx: bsv.Transaction): Promise<number> {
const copy = new bsv.Transaction(tx.uncheckedSerialize());
// use a copy bcoz `feePerKb` resets all the signatures for inputs.
copy.feePerKb(await this.getFeePerKb());
return copy.getEstimateFee();
}

// Executions

/**
* Send a raw transaction hex string.
* @param rawTxHex The raw transaction hex string to send.
* @returns A promise which resolves to the hash of the transaction that has been sent.
*/
abstract sendRawTransaction(rawTxHex: string): Promise<TxHash>;

/**
* Send a transaction object.
* @param tx The transaction object to send.
* @returns A promise which resolves to the hash of the transaction that has been sent.
* @throws If there is a problem with the `tx` object during serialization.
*/
sendTransaction(tx: bsv.Transaction): Promise<TxHash> {
// TODO: fix tx.serialize issue
return this.sendRawTransaction(tx.serialize({ disableIsFullySigned: true }));
}

// Queries

/**
* Get a transaction from the network.
* @param txHash The hash value of the transaction.
* @returns The query result with the transaction information.
*/
abstract getTransaction(txHash: TxHash): Promise<TransactionResponse>

/**
* Get a list of the P2PKH UTXOs.
* @param address The address of the returned UTXOs belongs to.
* @param options The optional query conditions, see details in `UtxoQueryOptions`.
* @returns A promise which resolves to a list of UTXO for the query options.
*/
abstract listUnspent(address: AddressOption, options?: UtxoQueryOptions): Promise<UTXO[]>;

/**
* Get the balance of BSVs in satoshis for an address.
* @param address The query address.
* @returns A promise which resolves to the address balance status.
*/
abstract getBalance(address: AddressOption): Promise<{ confirmed: number, unconfirmed: number }>;

/**
* Get a list of UTXO for a certain contract instance.
* @param genesisTxHash The hash value of deployment transaction of the contract instance.
* @param outputIndex The output index of the deployment transaction of the contract instance.
* @returns A promise which resolves to a list of transaction UTXO.
*/
abstract getContractUTXOs(genesisTxHash: TxHash, outputIndex: number): Promise<UTXO[]>;

// Inspection

readonly _isProvider: boolean;

/**
* Check if an object is a `Provider`
* @param value The target object
* @returns Returns `true` if and only if `object` is a Provider.
*/
static isProvider(value: any): value is Provider {
return !!(value && value._isProvider);
}
}

It is recommended that your provider implements all abstract methods. For non-abstract methods, the default implementation is usually sufficient.

Example: WhatsonchainProvider

Let's walk through the process of implementing our own provider. In this example we'll implement a provider for WhatsOnChain (WoC).

  1. First let's implement the isConnected() and connect() functions. Because WoC doesn't need to maintan an open connection, not does it require any authentication by default, it's simply marked as connected by default. If your chosen provider does, here's probably the place to implement the connection logic.
isConnected(): boolean {
return true;
}

override async connect(): Promise<this> {
this.emit(ProviderEvent.Connected, true);
return Promise.resolve(this);
}
  1. Next, we'll implement the network functions. Here, your providers selected network can be toggled. WoC supports both the Bitcoin mainnet along with testnet, so we don't do further checking:
override async updateNetwork(network: bsv.Networks.Network): Promise<boolean> {
this._network = network;
this.emit(ProviderEvent.NetworkChange, network);
return Promise.resolve(true);
}

override async getNetwork(): Promise<bsv.Networks.Network> {
return Promise.resolve(this._network);
}

If your provider is only meant for the testnet, you could do something like this:

override async updateNetwork(network: bsv.Networks.Network): Promise<boolean> {
if (network != bsv.Networks.testnet) {
throw new Error('Network not supported.')
}
this._network = network;
this.emit(ProviderEvent.NetworkChange, network);
return Promise.resolve(true);
}
  1. Now let's set the transaction fee rate. In our example, we hard-code the value to be 50 satoshis per Kb:
override async getFeePerKb(): Promise<number> {
return Promise.resolve(50);
}
  1. Let's implement the function that will send the transaction data to our provider:
override async sendRawTransaction(rawTxHex: string): Promise<TxHash> {
// 1 second per KB
const size = Math.max(1, rawTxHex.length / 2 / 1024); //KB
const timeout = Math.max(10000, 1000 * size);
try {
const res = await superagent.post(
`${this.apiPrefix}/tx/raw`
)
.timeout({
response: timeout, // Wait 5 seconds for the server to start sending,
deadline: 60000, // but allow 1 minute for the file to finish loading.
})
.set('Content-Type', 'application/json')
.send({ txhex: rawTxHex })
return res.body;
} catch (error) {
if (error.response && error.response.text) {
throw new Error(`WhatsonchainProvider ERROR: ${error.response.text}`)
}
throw new Error(`WhatsonchainProvider ERROR: ${error.message}`)
}
}

In the function we use the superagent to send requests to WoC's HTTP endpoint. Check out their docs for a description of the endpoints they provide.

  1. Now we need to implement some queries. First let's implement the function to get a list of UTXO's for a certain address:
override async listUnspent(
address: AddressOption,
options?: UtxoQueryOptions
): Promise<UTXO[]> {

const res = await superagent.get(`${this.apiPrefix}/address/${address}/unspent`);
const utxos: UTXO[] =
res.body.map(item => ({
txId: item.tx_hash,
outputIndex: item.tx_pos,
satoshis: item.value,
script: bsv.Script.buildPublicKeyHashOut(address).toHex(),
}));

if (options?.minSatoshis && utxos.reduce((s, u) => s + u.satoshis, 0) < options.minSatoshis) {
throw new Error(`WhatsonchainProvider ERROR: not enough utxos for the request amount of ${options.minSatoshis} on address ${address.toString()}`);
}

return utxos;
}

Next, we'll make the getBalance function parse out the addresses balance from the UTXO's:

override async getBalance(
address?: AddressOption
): Promise<{ confirmed: number, unconfirmed: number }> {

return this.listUnspent(address, { minSatoshis: 0 }).then(utxos => {
return {
confirmed: utxos.reduce((acc, utxo) => {
acc += utxo.satoshis;
return acc;
}, 0),
unconfirmed: 0
}
})

}

We also implement the function to query the raw transaction using the transactions ID:

override async getTransaction(txHash: string): Promise<TransactionResponse> {
try {
const res = await superagent.get(`${this.apiPrefix}/tx/${txHash}/hex`);
return new bsv.Transaction(res.text)
} catch (e) {
throw new Error(`WhatsonchainProvider ERROR: failed fetching raw transaction data: ${e.message}`);
}
}

Lastly, if our provider doesn't support a certain query, we can simply throw an error by default:

override async getContractUTXOs(genesisTxHash: string, outputIndex?: number): Promise<UTXO[]> {
throw new Error("Method #getContractUTXOs not implemented in WhatsonchainProvider.");
}

Using the Provider

Providers are usually used by a Signer:

const provider = new WhatsonchainProvider(bsv.Networks.mainnet)
const signer = new TestWallet(privateKey, provider)

await contractInstance.connect(signer);

Here, the signer will use our WhatsonchainProvider for each Bitcoin network operation it needs. The next section describes signers and how we can implement a custom one.

- - +

How to Add a Provider

In the contract testing section, we learned about the Provider class in sCrypt. This class serves as an abstraction of a Bitcoin node, allowing your application to communicate with the Bitcoin network.

sCrypt provides the following providers by default:

  • DummyProvider: A mockup provider intended for local testing. It does not connect to the Bitcoin blockchain and thus cannot send transactions.

  • DefaultProvider: The default provider is the safest and easiest way to begin developing on Bitcoin, and is also robust enough for use in production. It can be used in testnet as well as mainnet.

  • For a full list of providers, see here.

Implementation

Base Class Provider

To implement your own provider, you must extend the base class Provider. Here's the definition of this class:

/**
* A Provider is an abstraction of non-account-based operations on a blockchain and is generally not directly involved in signing transaction or data.
*/
export abstract class Provider extends EventEmitter {

constructor() {
super()
this._isProvider = true;
}

/**
* check if provider is ready
*/
abstract isConnected(): boolean;

/**
* Implement the connection provider, for example, verify the api key during the connection process.
* @returns a connected provider. Throw an exception if the connection fails.
*/
abstract connect(): Promise<this>;

/**
* update provider network
* @param network Network type to be updated
*/
abstract updateNetwork(network: bsv.Networks.Network): Promise<boolean>;

/**
* @returns The network this provider is connected to.
*/
abstract getNetwork(): Promise<bsv.Networks.Network>;

/**
* @returns The fee rate for sending transactions through this provider.
*/
abstract getFeePerKb(): Promise<number>;

/**
* Get a best guess of the fee for a transaction.
* @param tx A transaction object to estimate.
* @returns The estimated fee in satoshis.
*/
async getEstimateFee(tx: bsv.Transaction): Promise<number> {
const copy = new bsv.Transaction(tx.uncheckedSerialize());
// use a copy bcoz `feePerKb` resets all the signatures for inputs.
copy.feePerKb(await this.getFeePerKb());
return copy.getEstimateFee();
}

// Executions

/**
* Send a raw transaction hex string.
* @param rawTxHex The raw transaction hex string to send.
* @returns A promise which resolves to the hash of the transaction that has been sent.
*/
abstract sendRawTransaction(rawTxHex: string): Promise<TxHash>;

/**
* Send a transaction object.
* @param tx The transaction object to send.
* @returns A promise which resolves to the hash of the transaction that has been sent.
* @throws If there is a problem with the `tx` object during serialization.
*/
sendTransaction(tx: bsv.Transaction): Promise<TxHash> {
// TODO: fix tx.serialize issue
return this.sendRawTransaction(tx.serialize({ disableIsFullySigned: true }));
}

// Queries

/**
* Get a transaction from the network.
* @param txHash The hash value of the transaction.
* @returns The query result with the transaction information.
*/
abstract getTransaction(txHash: TxHash): Promise<TransactionResponse>

/**
* Get a list of the P2PKH UTXOs.
* @param address The address of the returned UTXOs belongs to.
* @param options The optional query conditions, see details in `UtxoQueryOptions`.
* @returns A promise which resolves to a list of UTXO for the query options.
*/
abstract listUnspent(address: AddressOption, options?: UtxoQueryOptions): Promise<UTXO[]>;

/**
* Get the balance of BSVs in satoshis for an address.
* @param address The query address.
* @returns A promise which resolves to the address balance status.
*/
abstract getBalance(address: AddressOption): Promise<{ confirmed: number, unconfirmed: number }>;

/**
* Get a list of UTXO for a certain contract instance.
* @param genesisTxHash The hash value of deployment transaction of the contract instance.
* @param outputIndex The output index of the deployment transaction of the contract instance.
* @returns A promise which resolves to a list of transaction UTXO.
*/
abstract getContractUTXOs(genesisTxHash: TxHash, outputIndex: number): Promise<UTXO[]>;

// Inspection

readonly _isProvider: boolean;

/**
* Check if an object is a `Provider`
* @param value The target object
* @returns Returns `true` if and only if `object` is a Provider.
*/
static isProvider(value: any): value is Provider {
return !!(value && value._isProvider);
}
}

It is recommended that your provider implements all abstract methods. For non-abstract methods, the default implementation is usually sufficient.

Example: WhatsonchainProvider

Let's walk through the process of implementing our own provider. In this example we'll implement a provider for WhatsOnChain (WoC).

  1. First let's implement the isConnected() and connect() functions. Because WoC doesn't need to maintan an open connection, not does it require any authentication by default, it's simply marked as connected by default. If your chosen provider does, here's probably the place to implement the connection logic.
isConnected(): boolean {
return true;
}

override async connect(): Promise<this> {
this.emit(ProviderEvent.Connected, true);
return Promise.resolve(this);
}
  1. Next, we'll implement the network functions. Here, your providers selected network can be toggled. WoC supports both the Bitcoin mainnet along with testnet, so we don't do further checking:
override async updateNetwork(network: bsv.Networks.Network): Promise<boolean> {
this._network = network;
this.emit(ProviderEvent.NetworkChange, network);
return Promise.resolve(true);
}

override async getNetwork(): Promise<bsv.Networks.Network> {
return Promise.resolve(this._network);
}

If your provider is only meant for the testnet, you could do something like this:

override async updateNetwork(network: bsv.Networks.Network): Promise<boolean> {
if (network != bsv.Networks.testnet) {
throw new Error('Network not supported.')
}
this._network = network;
this.emit(ProviderEvent.NetworkChange, network);
return Promise.resolve(true);
}
  1. Now let's set the transaction fee rate. In our example, we hard-code the value to be 50 satoshis per Kb:
override async getFeePerKb(): Promise<number> {
return Promise.resolve(50);
}
  1. Let's implement the function that will send the transaction data to our provider:
override async sendRawTransaction(rawTxHex: string): Promise<TxHash> {
// 1 second per KB
const size = Math.max(1, rawTxHex.length / 2 / 1024); //KB
const timeout = Math.max(10000, 1000 * size);
try {
const res = await superagent.post(
`${this.apiPrefix}/tx/raw`
)
.timeout({
response: timeout, // Wait 5 seconds for the server to start sending,
deadline: 60000, // but allow 1 minute for the file to finish loading.
})
.set('Content-Type', 'application/json')
.send({ txhex: rawTxHex })
return res.body;
} catch (error) {
if (error.response && error.response.text) {
throw new Error(`WhatsonchainProvider ERROR: ${error.response.text}`)
}
throw new Error(`WhatsonchainProvider ERROR: ${error.message}`)
}
}

In the function we use the superagent to send requests to WoC's HTTP endpoint. Check out their docs for a description of the endpoints they provide.

  1. Now we need to implement some queries. First let's implement the function to get a list of UTXO's for a certain address:
override async listUnspent(
address: AddressOption,
options?: UtxoQueryOptions
): Promise<UTXO[]> {

const res = await superagent.get(`${this.apiPrefix}/address/${address}/unspent`);
const utxos: UTXO[] =
res.body.map(item => ({
txId: item.tx_hash,
outputIndex: item.tx_pos,
satoshis: item.value,
script: bsv.Script.buildPublicKeyHashOut(address).toHex(),
}));

if (options?.minSatoshis && utxos.reduce((s, u) => s + u.satoshis, 0) < options.minSatoshis) {
throw new Error(`WhatsonchainProvider ERROR: not enough utxos for the request amount of ${options.minSatoshis} on address ${address.toString()}`);
}

return utxos;
}

Next, we'll make the getBalance function parse out the addresses balance from the UTXO's:

override async getBalance(
address?: AddressOption
): Promise<{ confirmed: number, unconfirmed: number }> {

return this.listUnspent(address, { minSatoshis: 0 }).then(utxos => {
return {
confirmed: utxos.reduce((acc, utxo) => {
acc += utxo.satoshis;
return acc;
}, 0),
unconfirmed: 0
}
})

}

We also implement the function to query the raw transaction using the transactions ID:

override async getTransaction(txHash: string): Promise<TransactionResponse> {
try {
const res = await superagent.get(`${this.apiPrefix}/tx/${txHash}/hex`);
return new bsv.Transaction(res.text)
} catch (e) {
throw new Error(`WhatsonchainProvider ERROR: failed fetching raw transaction data: ${e.message}`);
}
}

Lastly, if our provider doesn't support a certain query, we can simply throw an error by default:

override async getContractUTXOs(genesisTxHash: string, outputIndex?: number): Promise<UTXO[]> {
throw new Error("Method #getContractUTXOs not implemented in WhatsonchainProvider.");
}

Using the Provider

Providers are usually used by a Signer:

const provider = new WhatsonchainProvider(bsv.Networks.mainnet)
const signer = new TestWallet(privateKey, provider)

await contractInstance.connect(signer);

Here, the signer will use our WhatsonchainProvider for each Bitcoin network operation it needs. The next section describes signers and how we can implement a custom one.

+ + \ No newline at end of file diff --git a/advanced/how-to-add-a-signer/index.html b/advanced/how-to-add-a-signer/index.html index 663197142..251584298 100644 --- a/advanced/how-to-add-a-signer/index.html +++ b/advanced/how-to-add-a-signer/index.html @@ -4,13 +4,13 @@ How to Add a Signer | sCrypt - - + +
-

How to Add a Signer

As described in this section, a signer is an abstraction of private keys, which can be used to sign messages and transactions. A simple signer would be a single private key, while a complex signer is a wallet.

sCrypt provides the following signers by default:

  1. TestWallet : a simple wallet that can hold multiple private keys, with in-memory utxo management. Should only be used for testing.
  2. PandaSigner: a signer powered by the popular smart contract wallet Panda. Can be used in production.
  3. PandaSigner: another signer powered by the popular web3 wallet Panda. Can be used in production.

Implementation

Base Class Signer

If you want to implement your own signer, you must inherit from the base class Signer.

/**
* A `Signer` is a class which in some way directly or indirectly has access to a private key, which can sign messages and transactions to authorize the network to perform operations.
*/
export abstract class Signer {

provider?: Provider;
readonly _isSigner: boolean;

constructor(provider?: Provider) {
this._isSigner = true;
this.provider = provider;
}

abstract getNetwork(): Promise<bsv.Networks.Network>;

/**
* Check if the wallet has been authenticated
* @returns {boolean} true | false
*/
abstract isAuthenticated(): Promise<boolean>;

/**
* Request wallet authentication
* @returns A promise which resolves to if the wallet has been authenticated and the authenticate error message
*/
abstract requestAuth(): Promise<{ isAuthenticated: boolean, error: string }>;

/**
* Connect a provider to `this`.
* @param provider The target provider.
* @returns
*/
abstract connect(provider: Provider): Promise<this>;

// Account

/**
*
* @returns A promise which resolves to the address to the default private key of the signer.
*/
abstract getDefaultAddress(): Promise<bsv.Address>;

/**
*
* @returns A promise which resolves to the public key of the default private key of the signer.
*/
abstract getDefaultPubKey(): Promise<bsv.PublicKey>;

/**
*
* @param address The request address, using the default address if omitted.
* @returns The public key result.
* @throws If the private key for the address does not belong this signer.
*/
abstract getPubKey(address?: AddressOption): Promise<bsv.PublicKey>;

// Signing

/**
* Sign a raw transaction hex string.
*
* @param rawTxHex The raw transaction hex to sign.
* @param options The options for signing, see the details of `SignTransactionOptions`.
* @returns A promise which resolves to the signed transaction hex string.
* @throws If any input of the transaction can not be signed properly.
*/
async signRawTransaction(rawTxHex: string, options: SignTransactionOptions): Promise<string> {
...
}

/**
* Sign a transaction object.
* @param tx The transaction object to sign.
* @param options The options for signing, see the details of `SignTransactionOptions`.
* @returns A promise which resolves to the signed transaction object.
*/
async signTransaction(tx: bsv.Transaction, options?: SignTransactionOptions): Promise<bsv.Transaction>{
...
}

/**
* Sign a message string.
* @param message The message to be signed.
* @param address The optional address whose private key will be used to sign `message`, using the default private key if omitted.
* @returns A promise which resolves to the signautre of the message.
*/
abstract signMessage(message: string, address?: AddressOption): Promise<string>;

/**
* Get the requested transaction signatures for the raw transaction.
* @param rawTxHex The raw transaction hex to get signatures from.
* @param sigRequests The signature requst informations, see details in `SignatureRequest`.
* @returns A promise which resolves to a list of `SignatureReponse` corresponding to `sigRequests`.
*/
abstract getSignatures(rawTxHex: string, sigRequests: SignatureRequest[]): Promise<SignatureResponse[]>;

/**
* Get the connected provider.
* @returns the connected provider.
* @throws if no provider is connected to `this`.
*/
get connectedProvider(): Provider {
if (!this.provider) {
throw new Error(`the provider of singer ${this.constructor.name} is not set yet!`);
}
if (!this.provider.isConnected()) {
throw new Error(`the provider of singer ${this.constructor.name} is not connected yet!`);
}

return this.provider;
}

/**
* Sign the transaction, then broadcast the transaction
* @param tx A transaction is signed and broadcast
* @param options The options for signing, see the details of `SignTransactionOptions`.
* @returns A promise which resolves to the transaction id.
*/
async signAndsendTransaction(tx: bsv.Transaction, options?: SignTransactionOptions): Promise<TransactionResponse> {
await tx.sealAsync();
const signedTx = await this.signTransaction(tx, options);
await this.connectedProvider.sendTransaction(signedTx);
return signedTx;
};

/**
* Get a list of the P2PKH UTXOs.
* @param address The address of the returned UTXOs belongs to.
* @param options The optional query conditions, see details in `UtxoQueryOptions`.
* @returns A promise which resolves to a list of UTXO for the query options.
*/
listUnspent(address: AddressOption, options?: UtxoQueryOptions): Promise<UTXO[]> {
// default implemention using provider, can be overrided.
return this.connectedProvider.listUnspent(address, options);
}

/**
* Get the balance of BSVs in satoshis for an address.
* @param address The query address.
* @returns A promise which resolves to the address balance status.
*/
getBalance(address?: AddressOption): Promise<{ confirmed: number, unconfirmed: number }> {
// default implemention using provider, can be overrided.
return this.connectedProvider.getBalance(address);
}

// Inspection
/**
* Check if an object is a `Signer`
* @param value The target object
* @returns Returns `true` if and only if `object` is a Provider.
*/
static isSigner(value: any): value is Signer {
return !!(value && value._isSigner);
}

}

It is recommended that your signer implements all abstract methods. For non-abstract methods, the default implementation is usually sufficient.

Example: PandaSigner

Next, we use the Panda Wallet as an example to show how to implement a PandaSigner.

  1. Implement the isAuthenticated method to Check if the wallet has been authenticated:

private _initTarget() {
if(this._target) {
return;
}

if (typeof (window as any).panda !== 'undefined') {
this._target = (window as any).panda;
} else {
throw new Error('panda is not installed')
}
}

/**
* Check if the wallet has been authenticated
* @returns {boolean} true | false
*/
override isAuthenticated(): Promise<boolean> {
this._initTarget();
return this._target.isConnected();
}
  1. Implement the requestAuth method to request wallet authentication:
/**
* Request wallet authentication
* @returns A promise which resolves to if the wallet has been authenticated and the authenticate error message
*/
override async requestAuth(): Promise<{ isAuthenticated: boolean, error: string }> {
let isAuthenticated: boolean = false
let error: string = ''
try {
await this.getConnectedTarget()
await this.alignProviderNetwork()
isAuthenticated = true
} catch (e) {
error = e.toString()
}
return Promise.resolve({ isAuthenticated, error })
}
  1. In the connect method, you usually attempt to connect to a provider and save it:
override async connect(provider?: Provider): Promise<this> {
// we should make sure panda is connected before we connect a provider.
const isAuthenticated = await this.isAuthenticated();

if (!isAuthenticated) {
throw new Error('panda is not connected!');
}

if (provider) {
if (!provider.isConnected()) {
await provider.connect();
}
this.provider = provider;
} else {
if (this.provider) {
await this.provider.connect();
} else {
throw new Error(`No provider found`);
}
}

return this;
}

  1. Returns the address to the default private key of the wallet in getDefaultAddress:
/**
* Get an object that can directly interact with the Panda wallet,
* if there is no connection with the wallet, it will request to establish a connection.
* @returns PandaAPI
*/
private async getConnectedTarget(): Promise<PandaAPI> {
const isAuthenticated = await this.isAuthenticated()
if (!isAuthenticated) {
// trigger connecting to panda account when it's not authorized.
try {

this._initTarget();
const res = await this._target.connect();

if(res && res.includes("canceled")) {
throw new Error(res);
}

} catch (e) {
throw new Error(`panda requestAccount failed: ${e}`)
}
}
return this._target;
}

override async getDefaultAddress(): Promise<bsv.Address> {
const panda = await this.getConnectedTarget();
const address = await panda.getAddresses();
return bsv.Address.fromString(address.bsvAddress);
}
  1. Returns the public key to the default private key of the wallet in getDefaultPubKey:
override async getDefaultPubKey(): Promise<bsv.PublicKey> {
const panda = await this.getConnectedTarget();
const pubKey = await panda.getPubKeys();
return Promise.resolve(new bsv.PublicKey(pubKey.bsvPubKey));
}
  1. Since Panda is a single-address wallet, we simply ignore the getPubKey method:
override async getPubKey(address: AddressOption): Promise<PublicKey> {
throw new Error(`Method ${this.constructor.name}#getPubKey not implemented.`);
}
  1. Both signTransaction and signRawTransaction sign the transaction, and are already implemented in the base class. You just need to implement the getSignatures function. The following code calls panda's getSignatures API to request a panda wallet signature.

/**
* Get signatures with Panda api
* @param rawTxHex a transation raw hex
* @param sigRequests a `SignatureRequest` array for the some inputs of the transaction.
* @returns a `SignatureResponse` array
*/
override async getSignatures(rawTxHex: string, sigRequests: SignatureRequest[]): Promise<SignatureResponse[]> {
const panda = await this.getConnectedTarget();
const network = await this.getNetwork()

const sigRequests_ = sigRequests.map(sigReq => ({
prevTxid: sigReq.prevTxId,
outputIndex: sigReq.outputIndex,
inputIndex: sigReq.inputIndex,
satoshis: sigReq.satoshis,
address: parseAddresses(sigReq.address, network).map(addr => addr.toString()),
script: sigReq.scriptHex,
sigHashType: sigReq.sigHashType,
csIdx: sigReq.csIdx,
data: sigReq.data,
}));

const sigResults = await panda.getSignatures({
rawtx: rawTxHex,
sigRequests: sigRequests_
});

return sigResults.map(sigResult => ({
...sigResult,
publicKey: sigResult.pubKey,
}));
}
  1. Panda supports signing messages, if your wallet does not support it, you can throw an exception in the signMessage function:
override async signMessage(message: string, address?: AddressOption): Promise<string> {
if (address) {
throw new Error(`${this.constructor.name}#signMessge with \`address\` param is not supported!`);
}
const panda = await this.getConnectedTarget();
const res = await panda.signMessage({message});
return res.sig;
}

So far, we have implemented all abstract methods. The remaining non-abstract methods can reuse the default implementation, that is, delegating to the connected provider. If you have a customized implementation, you can override them. For example, we can use the Panda api getBalance to obtain the balance of an address.

override getBalance(address?: AddressOption): Promise<{ confirmed: number, unconfirmed: number }> {
if (address) {
return this.connectedProvider.getBalance(address);
}

const panda = await this.getConnectedTarget();
const balance = await panda.getBalance();
return Promise.resolve({ confirmed: balance.satoshis, unconfirmed: 0 });
}

Now we have implemented PandaSigner. The full code is here.

Use your signer

Just connect your signer to a smart contract instance like any other signers:

// declare your signer
const your_signer = new YourSigner(new DefaultProvider());
// connect the signer to the contract instance
await instance.connect(your_signer);

Here is another user-customized signer.

- - +

How to Add a Signer

As described in this section, a signer is an abstraction of private keys, which can be used to sign messages and transactions. A simple signer would be a single private key, while a complex signer is a wallet.

sCrypt provides the following signers by default:

  1. TestWallet : a simple wallet that can hold multiple private keys, with in-memory utxo management. Should only be used for testing.
  2. PandaSigner: a signer powered by the popular smart contract wallet Panda. Can be used in production.
  3. PandaSigner: another signer powered by the popular web3 wallet Panda. Can be used in production.

Implementation

Base Class Signer

If you want to implement your own signer, you must inherit from the base class Signer.

/**
* A `Signer` is a class which in some way directly or indirectly has access to a private key, which can sign messages and transactions to authorize the network to perform operations.
*/
export abstract class Signer {

provider?: Provider;
readonly _isSigner: boolean;

constructor(provider?: Provider) {
this._isSigner = true;
this.provider = provider;
}

abstract getNetwork(): Promise<bsv.Networks.Network>;

/**
* Check if the wallet has been authenticated
* @returns {boolean} true | false
*/
abstract isAuthenticated(): Promise<boolean>;

/**
* Request wallet authentication
* @returns A promise which resolves to if the wallet has been authenticated and the authenticate error message
*/
abstract requestAuth(): Promise<{ isAuthenticated: boolean, error: string }>;

/**
* Connect a provider to `this`.
* @param provider The target provider.
* @returns
*/
abstract connect(provider: Provider): Promise<this>;

// Account

/**
*
* @returns A promise which resolves to the address to the default private key of the signer.
*/
abstract getDefaultAddress(): Promise<bsv.Address>;

/**
*
* @returns A promise which resolves to the public key of the default private key of the signer.
*/
abstract getDefaultPubKey(): Promise<bsv.PublicKey>;

/**
*
* @param address The request address, using the default address if omitted.
* @returns The public key result.
* @throws If the private key for the address does not belong this signer.
*/
abstract getPubKey(address?: AddressOption): Promise<bsv.PublicKey>;

// Signing

/**
* Sign a raw transaction hex string.
*
* @param rawTxHex The raw transaction hex to sign.
* @param options The options for signing, see the details of `SignTransactionOptions`.
* @returns A promise which resolves to the signed transaction hex string.
* @throws If any input of the transaction can not be signed properly.
*/
async signRawTransaction(rawTxHex: string, options: SignTransactionOptions): Promise<string> {
...
}

/**
* Sign a transaction object.
* @param tx The transaction object to sign.
* @param options The options for signing, see the details of `SignTransactionOptions`.
* @returns A promise which resolves to the signed transaction object.
*/
async signTransaction(tx: bsv.Transaction, options?: SignTransactionOptions): Promise<bsv.Transaction>{
...
}

/**
* Sign a message string.
* @param message The message to be signed.
* @param address The optional address whose private key will be used to sign `message`, using the default private key if omitted.
* @returns A promise which resolves to the signautre of the message.
*/
abstract signMessage(message: string, address?: AddressOption): Promise<string>;

/**
* Get the requested transaction signatures for the raw transaction.
* @param rawTxHex The raw transaction hex to get signatures from.
* @param sigRequests The signature requst informations, see details in `SignatureRequest`.
* @returns A promise which resolves to a list of `SignatureReponse` corresponding to `sigRequests`.
*/
abstract getSignatures(rawTxHex: string, sigRequests: SignatureRequest[]): Promise<SignatureResponse[]>;

/**
* Get the connected provider.
* @returns the connected provider.
* @throws if no provider is connected to `this`.
*/
get connectedProvider(): Provider {
if (!this.provider) {
throw new Error(`the provider of singer ${this.constructor.name} is not set yet!`);
}
if (!this.provider.isConnected()) {
throw new Error(`the provider of singer ${this.constructor.name} is not connected yet!`);
}

return this.provider;
}

/**
* Sign the transaction, then broadcast the transaction
* @param tx A transaction is signed and broadcast
* @param options The options for signing, see the details of `SignTransactionOptions`.
* @returns A promise which resolves to the transaction id.
*/
async signAndsendTransaction(tx: bsv.Transaction, options?: SignTransactionOptions): Promise<TransactionResponse> {
await tx.sealAsync();
const signedTx = await this.signTransaction(tx, options);
await this.connectedProvider.sendTransaction(signedTx);
return signedTx;
};

/**
* Get a list of the P2PKH UTXOs.
* @param address The address of the returned UTXOs belongs to.
* @param options The optional query conditions, see details in `UtxoQueryOptions`.
* @returns A promise which resolves to a list of UTXO for the query options.
*/
listUnspent(address: AddressOption, options?: UtxoQueryOptions): Promise<UTXO[]> {
// default implemention using provider, can be overrided.
return this.connectedProvider.listUnspent(address, options);
}

/**
* Get the balance of BSVs in satoshis for an address.
* @param address The query address.
* @returns A promise which resolves to the address balance status.
*/
getBalance(address?: AddressOption): Promise<{ confirmed: number, unconfirmed: number }> {
// default implemention using provider, can be overrided.
return this.connectedProvider.getBalance(address);
}

// Inspection
/**
* Check if an object is a `Signer`
* @param value The target object
* @returns Returns `true` if and only if `object` is a Provider.
*/
static isSigner(value: any): value is Signer {
return !!(value && value._isSigner);
}

}

It is recommended that your signer implements all abstract methods. For non-abstract methods, the default implementation is usually sufficient.

Example: PandaSigner

Next, we use the Panda Wallet as an example to show how to implement a PandaSigner.

  1. Implement the isAuthenticated method to Check if the wallet has been authenticated:

private _initTarget() {
if(this._target) {
return;
}

if (typeof (window as any).panda !== 'undefined') {
this._target = (window as any).panda;
} else {
throw new Error('panda is not installed')
}
}

/**
* Check if the wallet has been authenticated
* @returns {boolean} true | false
*/
override isAuthenticated(): Promise<boolean> {
this._initTarget();
return this._target.isConnected();
}
  1. Implement the requestAuth method to request wallet authentication:
/**
* Request wallet authentication
* @returns A promise which resolves to if the wallet has been authenticated and the authenticate error message
*/
override async requestAuth(): Promise<{ isAuthenticated: boolean, error: string }> {
let isAuthenticated: boolean = false
let error: string = ''
try {
await this.getConnectedTarget()
await this.alignProviderNetwork()
isAuthenticated = true
} catch (e) {
error = e.toString()
}
return Promise.resolve({ isAuthenticated, error })
}
  1. In the connect method, you usually attempt to connect to a provider and save it:
override async connect(provider?: Provider): Promise<this> {
// we should make sure panda is connected before we connect a provider.
const isAuthenticated = await this.isAuthenticated();

if (!isAuthenticated) {
throw new Error('panda is not connected!');
}

if (provider) {
if (!provider.isConnected()) {
await provider.connect();
}
this.provider = provider;
} else {
if (this.provider) {
await this.provider.connect();
} else {
throw new Error(`No provider found`);
}
}

return this;
}

  1. Returns the address to the default private key of the wallet in getDefaultAddress:
/**
* Get an object that can directly interact with the Panda wallet,
* if there is no connection with the wallet, it will request to establish a connection.
* @returns PandaAPI
*/
private async getConnectedTarget(): Promise<PandaAPI> {
const isAuthenticated = await this.isAuthenticated()
if (!isAuthenticated) {
// trigger connecting to panda account when it's not authorized.
try {

this._initTarget();
const res = await this._target.connect();

if(res && res.includes("canceled")) {
throw new Error(res);
}

} catch (e) {
throw new Error(`panda requestAccount failed: ${e}`)
}
}
return this._target;
}

override async getDefaultAddress(): Promise<bsv.Address> {
const panda = await this.getConnectedTarget();
const address = await panda.getAddresses();
return bsv.Address.fromString(address.bsvAddress);
}
  1. Returns the public key to the default private key of the wallet in getDefaultPubKey:
override async getDefaultPubKey(): Promise<bsv.PublicKey> {
const panda = await this.getConnectedTarget();
const pubKey = await panda.getPubKeys();
return Promise.resolve(new bsv.PublicKey(pubKey.bsvPubKey));
}
  1. Since Panda is a single-address wallet, we simply ignore the getPubKey method:
override async getPubKey(address: AddressOption): Promise<PublicKey> {
throw new Error(`Method ${this.constructor.name}#getPubKey not implemented.`);
}
  1. Both signTransaction and signRawTransaction sign the transaction, and are already implemented in the base class. You just need to implement the getSignatures function. The following code calls panda's getSignatures API to request a panda wallet signature.

/**
* Get signatures with Panda api
* @param rawTxHex a transation raw hex
* @param sigRequests a `SignatureRequest` array for the some inputs of the transaction.
* @returns a `SignatureResponse` array
*/
override async getSignatures(rawTxHex: string, sigRequests: SignatureRequest[]): Promise<SignatureResponse[]> {
const panda = await this.getConnectedTarget();
const network = await this.getNetwork()

const sigRequests_ = sigRequests.map(sigReq => ({
prevTxid: sigReq.prevTxId,
outputIndex: sigReq.outputIndex,
inputIndex: sigReq.inputIndex,
satoshis: sigReq.satoshis,
address: parseAddresses(sigReq.address, network).map(addr => addr.toString()),
script: sigReq.scriptHex,
sigHashType: sigReq.sigHashType,
csIdx: sigReq.csIdx,
data: sigReq.data,
}));

const sigResults = await panda.getSignatures({
rawtx: rawTxHex,
sigRequests: sigRequests_
});

return sigResults.map(sigResult => ({
...sigResult,
publicKey: sigResult.pubKey,
}));
}
  1. Panda supports signing messages, if your wallet does not support it, you can throw an exception in the signMessage function:
override async signMessage(message: string, address?: AddressOption): Promise<string> {
if (address) {
throw new Error(`${this.constructor.name}#signMessge with \`address\` param is not supported!`);
}
const panda = await this.getConnectedTarget();
const res = await panda.signMessage({message});
return res.sig;
}

So far, we have implemented all abstract methods. The remaining non-abstract methods can reuse the default implementation, that is, delegating to the connected provider. If you have a customized implementation, you can override them. For example, we can use the Panda api getBalance to obtain the balance of an address.

override getBalance(address?: AddressOption): Promise<{ confirmed: number, unconfirmed: number }> {
if (address) {
return this.connectedProvider.getBalance(address);
}

const panda = await this.getConnectedTarget();
const balance = await panda.getBalance();
return Promise.resolve({ confirmed: balance.satoshis, unconfirmed: 0 });
}

Now we have implemented PandaSigner. The full code is here.

Use your signer

Just connect your signer to a smart contract instance like any other signers:

// declare your signer
const your_signer = new YourSigner(new DefaultProvider());
// connect the signer to the contract instance
await instance.connect(your_signer);

Here is another user-customized signer.

+ + \ No newline at end of file diff --git a/advanced/how-to-build-an-oracle-service/index.html b/advanced/how-to-build-an-oracle-service/index.html index 28e51cccf..852089e91 100644 --- a/advanced/how-to-build-an-oracle-service/index.html +++ b/advanced/how-to-build-an-oracle-service/index.html @@ -4,13 +4,13 @@ How to Build an Oracle Service | sCrypt - - + +
-

How to Build an Oracle Service

As described in this tutorial, a blockchain oracle is a third-party service or agent that provides external data to a blockchain network. It is a bridge between the blockchain and the external world, enabling smart contracts to access, verify, and incorporate data from outside the blockchain. Specifically, the oracle service provides external data along with a Rabin signature of the data, and the smart contract uses this data and verifies the signature before using it.

Rabin signature

Rabin signature is an alternative digital signature algorithm (DSA) to ECDSA used in Bitcoin. It has a beautiful asymmetry that signature generation is computationally expensive, but signature verification is cheap. Therefore, we choose to use Rabin signature to ensure the integrity of the external data provided by the oracle. When an oracle provides data, it will sign the data with its private key off chain. When the data is used by smart contracts, its signature is verified on chain, which is cheap. We do not use the builtin checkSig opcode here because it can only check signature against the transaction data, not arbitrary data.

In this section, we will introduce how to build your own oracle service. For the backend framework, we use NestJS to illustrate, but you are free to use any familiar framework to build the service. For the Rabin signature part, we have already implemented a library rabinsig, which can be imported and used directly.

The full complete code of this demo can be found in our GitHub repo. You can also refer to the code of WitnessOnChain, an open-sourced oracle service, for more details.

1. Scaffold the project

Run the following command to create a NestJS project.

npx @nestjs/cli new oracle-demo

Then install dependencies.

cd oracle-demo
npm install
npm install rabinsig

2. Generate signatures

An oracle may provide multiple pieces of data, each requiring a signature. We implement a common service, so that it can be reused and called in different places.

The class SigService will load and initialize a private key from ENVs. We add a method sign in this class, which takes one parameter dataBuffer representing the binary data to be signed.

import { Rabin, serialize } from 'rabinsig';

export class SigService {
private rabin = new Rabin();
// load and init Rabin private key from ENVs
...
sign(dataBuffer: Buffer) {
const dataHex = dataBuffer.toString('hex');
const sig = this.rabin.sign(dataHex, this.privKey);
return { data: dataHex, signature: serialize(sig) };
}
}

3. Add APIs

Add a timestamp API

Too see how it works, we implement a simple timestamp API. We first get the current timestamp, then convert it to a 4 bytes Buffer in little-endian, and sign the structured data.

export function getTimestamp() {
return Math.trunc(Date.now() / 1000);
}

@Get('/timestamp')
getTimestamp() {
const timestamp = getTimestamp();
const data = Buffer.concat([
toBufferLE(V1Controller.MARKER.TIMESTAMP, 1), // api marker, 1 byte
toBufferLE(timestamp, 4), // timestamp, 4 bytes LE
]);
const sigResponse = this.rabinService.sign(data);
return { timestamp, ...sigResponse };
}

The response of this API is as follows.

{
"timestamp":1700596603,
"data":"017b0b5d65",
"signature":{
"s":"4fe8bbcdf26...",
"padding":"0000"
}
}

For the smart contract, it is only necessary to focus on two parts: data and signature. It should only use and trust data when the signature verification passes.

API Marker

Note that the first byte in data is an identification marker, which not only indicates how the signed data is serialized, but also has a more important role in distinguishing data from different interfaces.

Without this marker, the smart contract cannot distinguish which interface the passed data actually comes from. When oracle has two interfaces that return signed data of the same length, the attacker can pass the data returned from another interfaces to the contract, potentially causing issues. Therefore, different APIs should use different marker values.

Add a coin price API

Here we use the OKX API to obtain a currency's price.

First, wrap the OKX API. Note how the method handles the value of price. Because it is inconvenient for the smart contract to handle float numbers, a variable decimal is introduced to convert the price value into an integer.

/**
* @param tradingPair e.g. `BSV-USDT`, `BTC-USDC`, etc
* @param decimal decimal of the returned price
* @returns an integer representing the price of the trading pair, e.g. return 1234 with decimal 2 means 12.34
*/
async getOkxPrice(tradingPair: string, decimal: number) {
return axios
.get(`https://www.okx.com/api/v5/market/ticker?instId=${tradingPair}`)
.then((r) => Math.trunc(r.data.data[0].last * 10 ** decimal));
}

Then implement the oracle API following the order of obtaining data, serializing it, and signing it.

@Get('price/:base/:query')
async getPrice(@Param('base') base: string, @Param('query') query: string) {
// obtain data
const tradingPair = `${query.toUpperCase()}-${base.toUpperCase()}`;
const decimal = 4;
const price = await this.v1Service.getOkxPrice(tradingPair, decimal);
// serialize data
const timestamp = getTimestamp();
const data = Buffer.concat([
toBufferLE(V1Controller.MARKER.PRICE, 1), // api marker, 1 byte
toBufferLE(timestamp, 4), // timestamp, 4 bytes LE
toBufferLE(price, 8), // price, 8 bytes LE
toBufferLE(decimal, 1), // decimal, 1 byte
Buffer.from(tradingPair), // trading pair
]);
// sign data
const sigResponse = this.rabinService.sign(data);
return { timestamp, tradingPair, price, decimal, ...sigResponse };
}

Add more APIs

According to the previous introduction, you can add more APIs to your oracle as needed, such as obtaining BSV chain info, etc., which will not be covered here.

4. Use oralce data in a smart contract

In this tutorial, we introduce how to verify and use oracle data in smart contracts.

To verify signatures in smart contracts, we need to install the scrypt-ts-lib library.

npm install scrypt-ts-lib

Then add the contract under folder src/contracts. Here we also use the PriceBet contract. You can refer to file priceBet.e2e-spec.ts for a complete test code.

- - +

How to Build an Oracle Service

As described in this tutorial, a blockchain oracle is a third-party service or agent that provides external data to a blockchain network. It is a bridge between the blockchain and the external world, enabling smart contracts to access, verify, and incorporate data from outside the blockchain. Specifically, the oracle service provides external data along with a Rabin signature of the data, and the smart contract uses this data and verifies the signature before using it.

Rabin signature

Rabin signature is an alternative digital signature algorithm (DSA) to ECDSA used in Bitcoin. It has a beautiful asymmetry that signature generation is computationally expensive, but signature verification is cheap. Therefore, we choose to use Rabin signature to ensure the integrity of the external data provided by the oracle. When an oracle provides data, it will sign the data with its private key off chain. When the data is used by smart contracts, its signature is verified on chain, which is cheap. We do not use the builtin checkSig opcode here because it can only check signature against the transaction data, not arbitrary data.

In this section, we will introduce how to build your own oracle service. For the backend framework, we use NestJS to illustrate, but you are free to use any familiar framework to build the service. For the Rabin signature part, we have already implemented a library rabinsig, which can be imported and used directly.

The full complete code of this demo can be found in our GitHub repo. You can also refer to the code of WitnessOnChain, an open-sourced oracle service, for more details.

1. Scaffold the project

Run the following command to create a NestJS project.

npx @nestjs/cli new oracle-demo

Then install dependencies.

cd oracle-demo
npm install
npm install rabinsig

2. Generate signatures

An oracle may provide multiple pieces of data, each requiring a signature. We implement a common service, so that it can be reused and called in different places.

The class SigService will load and initialize a private key from ENVs. We add a method sign in this class, which takes one parameter dataBuffer representing the binary data to be signed.

import { Rabin, serialize } from 'rabinsig';

export class SigService {
private rabin = new Rabin();
// load and init Rabin private key from ENVs
...
sign(dataBuffer: Buffer) {
const dataHex = dataBuffer.toString('hex');
const sig = this.rabin.sign(dataHex, this.privKey);
return { data: dataHex, signature: serialize(sig) };
}
}

3. Add APIs

Add a timestamp API

Too see how it works, we implement a simple timestamp API. We first get the current timestamp, then convert it to a 4 bytes Buffer in little-endian, and sign the structured data.

export function getTimestamp() {
return Math.trunc(Date.now() / 1000);
}

@Get('/timestamp')
getTimestamp() {
const timestamp = getTimestamp();
const data = Buffer.concat([
toBufferLE(V1Controller.MARKER.TIMESTAMP, 1), // api marker, 1 byte
toBufferLE(timestamp, 4), // timestamp, 4 bytes LE
]);
const sigResponse = this.rabinService.sign(data);
return { timestamp, ...sigResponse };
}

The response of this API is as follows.

{
"timestamp":1700596603,
"data":"017b0b5d65",
"signature":{
"s":"4fe8bbcdf26...",
"padding":"0000"
}
}

For the smart contract, it is only necessary to focus on two parts: data and signature. It should only use and trust data when the signature verification passes.

API Marker

Note that the first byte in data is an identification marker, which not only indicates how the signed data is serialized, but also has a more important role in distinguishing data from different interfaces.

Without this marker, the smart contract cannot distinguish which interface the passed data actually comes from. When oracle has two interfaces that return signed data of the same length, the attacker can pass the data returned from another interfaces to the contract, potentially causing issues. Therefore, different APIs should use different marker values.

Add a coin price API

Here we use the OKX API to obtain a currency's price.

First, wrap the OKX API. Note how the method handles the value of price. Because it is inconvenient for the smart contract to handle float numbers, a variable decimal is introduced to convert the price value into an integer.

/**
* @param tradingPair e.g. `BSV-USDT`, `BTC-USDC`, etc
* @param decimal decimal of the returned price
* @returns an integer representing the price of the trading pair, e.g. return 1234 with decimal 2 means 12.34
*/
async getOkxPrice(tradingPair: string, decimal: number) {
return axios
.get(`https://www.okx.com/api/v5/market/ticker?instId=${tradingPair}`)
.then((r) => Math.trunc(r.data.data[0].last * 10 ** decimal));
}

Then implement the oracle API following the order of obtaining data, serializing it, and signing it.

@Get('price/:base/:query')
async getPrice(@Param('base') base: string, @Param('query') query: string) {
// obtain data
const tradingPair = `${query.toUpperCase()}-${base.toUpperCase()}`;
const decimal = 4;
const price = await this.v1Service.getOkxPrice(tradingPair, decimal);
// serialize data
const timestamp = getTimestamp();
const data = Buffer.concat([
toBufferLE(V1Controller.MARKER.PRICE, 1), // api marker, 1 byte
toBufferLE(timestamp, 4), // timestamp, 4 bytes LE
toBufferLE(price, 8), // price, 8 bytes LE
toBufferLE(decimal, 1), // decimal, 1 byte
Buffer.from(tradingPair), // trading pair
]);
// sign data
const sigResponse = this.rabinService.sign(data);
return { timestamp, tradingPair, price, decimal, ...sigResponse };
}

Add more APIs

According to the previous introduction, you can add more APIs to your oracle as needed, such as obtaining BSV chain info, etc., which will not be covered here.

4. Use oralce data in a smart contract

In this tutorial, we introduce how to verify and use oracle data in smart contracts.

To verify signatures in smart contracts, we need to install the scrypt-ts-lib library.

npm install scrypt-ts-lib

Then add the contract under folder src/contracts. Here we also use the PriceBet contract. You can refer to file priceBet.e2e-spec.ts for a complete test code.

+ + \ No newline at end of file diff --git a/advanced/how-to-call-multiple-contracts/index.html b/advanced/how-to-call-multiple-contracts/index.html index cd5b8c6c7..b474fc896 100644 --- a/advanced/how-to-call-multiple-contracts/index.html +++ b/advanced/how-to-call-multiple-contracts/index.html @@ -4,13 +4,13 @@ Call Multiple Contracts in a Single Tx | sCrypt - - + +
-

Call Multiple Contracts in a Single Tx

Up to now, we have only shown how to call one smart contract in a transaction. That is, only one input of the tx spends a smart contract UTXO, and the other inputs, if any, spend Pay-to-Public-Key-Hash (P2PKH) UTXOs, which are generally NOT regarded as smart contracts.

There are cases where it is desirable to spend multiple smart contract UTXOs in different inputs of a tx.

The main differences from calling a single contract are:

  1. Set multiContractCall = true in MethodCallOptions
  2. Each call may only return a partial/incomplete transaction, instead of a complete transaction
  3. A partial tx has to be passed as ContractTransaction in MethodCallOptions in subsequent calls
  4. Finally invoke SmartContract.multiContractCall(partialContractTx: ContractTransaction, signer: Signer) to sign and broadcast the complete transaction

The following is an example code of calling two contracts at the same time:

import { Counter } from '../../src/contracts/counter'
import { getDefaultSigner } from '../utils/helper'
import { HashPuzzle } from '../../src/contracts/hashPuzzle'

async function main() {
await Counter.loadArtifact()
await HashPuzzle.loadArtifact()

const signer = getDefaultSigner()
let counter = new Counter(1n)

// connect to a signer
await counter.connect(signer)

// contract deployment
const deployTx = await counter.deploy(1)
console.log('Counter contract deployed: ', deployTx.id)

counter.bindTxBuilder(
'incrementOnChain',
(
current: Counter,
options: MethodCallOptions<Counter>,
...args: any
): Promise<ContractTransaction> => {
// create the next instance from the current
const nextInstance = current.next()
// apply updates on the next instance locally
nextInstance.count++

const tx = new bsv.Transaction()
tx.addInput(current.buildContractInput()).addOutput(
new bsv.Transaction.Output({
script: nextInstance.lockingScript,
satoshis: current.balance,
})
)

return Promise.resolve({
tx: tx,
atInputIndex: 0,
nexts: [
{
instance: nextInstance,
balance: current.balance,
atOutputIndex: 0,
},
],
})
}
)

const plainText = 'abc'
const byteString = toByteString(plainText, true)
const sha256Data = sha256(byteString)

const hashPuzzle = new HashPuzzle(sha256Data)

// connect to a signer
await hashPuzzle.connect(signer)

const deployTx1 = await hashPuzzle.deploy(1)
console.log('HashPuzzle contract deployed: ', deployTx1.id)

hashPuzzle.bindTxBuilder(
'unlock',
(
current: HashPuzzle,
options: MethodCallOptions<HashPuzzle>,
...args: any
): Promise<ContractTransaction> => {
if (options.partialContractTx) {
const unSignedTx = options.partialContractTx.tx
unSignedTx.addInput(
current.buildContractInput()
)

return Promise.resolve({
tx: unSignedTx,
atInputIndex: 1,
nexts: [],
})
}

throw new Error('no partialContractTx found')
}
)

const partialTx = await counter.methods.incrementOnChain({
multiContractCall: true,
} as MethodCallOptions<Counter>)

const finalTx = await hashPuzzle.methods.unlock(
byteString,
{
multiContractCall: true,
partialContractTx: partialTx,
} as MethodCallOptions<HashPuzzle>
)

const { tx: callTx, nexts } = await SmartContract.multiContractCall(
finalTx,
signer
)

console.log('Counter, HashPuzzle contract `unlock` called: ', callTx.id)

// hashPuzzle has terminated, but counter can still be called
counter = nexts[0].instance
}

await main()

note
  • You must bind a transaction builder to each contract instance, since the default only spends a single contract UTXO.
  • If the called contracts need signatures from different private keys to be called, the signer passed to multiContractCall must have all private keys.
- - +

Call Multiple Contracts in a Single Tx

Up to now, we have only shown how to call one smart contract in a transaction. That is, only one input of the tx spends a smart contract UTXO, and the other inputs, if any, spend Pay-to-Public-Key-Hash (P2PKH) UTXOs, which are generally NOT regarded as smart contracts.

There are cases where it is desirable to spend multiple smart contract UTXOs in different inputs of a tx.

The main differences from calling a single contract are:

  1. Set multiContractCall = true in MethodCallOptions
  2. Each call may only return a partial/incomplete transaction, instead of a complete transaction
  3. A partial tx has to be passed as ContractTransaction in MethodCallOptions in subsequent calls
  4. Finally invoke SmartContract.multiContractCall(partialContractTx: ContractTransaction, signer: Signer) to sign and broadcast the complete transaction

The following is an example code of calling two contracts at the same time:

import { Counter } from '../../src/contracts/counter'
import { getDefaultSigner } from '../utils/helper'
import { HashPuzzle } from '../../src/contracts/hashPuzzle'

async function main() {
await Counter.loadArtifact()
await HashPuzzle.loadArtifact()

const signer = getDefaultSigner()
let counter = new Counter(1n)

// connect to a signer
await counter.connect(signer)

// contract deployment
const deployTx = await counter.deploy(1)
console.log('Counter contract deployed: ', deployTx.id)

counter.bindTxBuilder(
'incrementOnChain',
(
current: Counter,
options: MethodCallOptions<Counter>,
...args: any
): Promise<ContractTransaction> => {
// create the next instance from the current
const nextInstance = current.next()
// apply updates on the next instance locally
nextInstance.count++

const tx = new bsv.Transaction()
tx.addInput(current.buildContractInput()).addOutput(
new bsv.Transaction.Output({
script: nextInstance.lockingScript,
satoshis: current.balance,
})
)

return Promise.resolve({
tx: tx,
atInputIndex: 0,
nexts: [
{
instance: nextInstance,
balance: current.balance,
atOutputIndex: 0,
},
],
})
}
)

const plainText = 'abc'
const byteString = toByteString(plainText, true)
const sha256Data = sha256(byteString)

const hashPuzzle = new HashPuzzle(sha256Data)

// connect to a signer
await hashPuzzle.connect(signer)

const deployTx1 = await hashPuzzle.deploy(1)
console.log('HashPuzzle contract deployed: ', deployTx1.id)

hashPuzzle.bindTxBuilder(
'unlock',
(
current: HashPuzzle,
options: MethodCallOptions<HashPuzzle>,
...args: any
): Promise<ContractTransaction> => {
if (options.partialContractTx) {
const unSignedTx = options.partialContractTx.tx
unSignedTx.addInput(
current.buildContractInput()
)

return Promise.resolve({
tx: unSignedTx,
atInputIndex: 1,
nexts: [],
})
}

throw new Error('no partialContractTx found')
}
)

const partialTx = await counter.methods.incrementOnChain({
multiContractCall: true,
} as MethodCallOptions<Counter>)

const finalTx = await hashPuzzle.methods.unlock(
byteString,
{
multiContractCall: true,
partialContractTx: partialTx,
} as MethodCallOptions<HashPuzzle>
)

const { tx: callTx, nexts } = await SmartContract.multiContractCall(
finalTx,
signer
)

console.log('Counter, HashPuzzle contract `unlock` called: ', callTx.id)

// hashPuzzle has terminated, but counter can still be called
counter = nexts[0].instance
}

await main()

note
  • You must bind a transaction builder to each contract instance, since the default only spends a single contract UTXO.
  • If the called contracts need signatures from different private keys to be called, the signer passed to multiContractCall must have all private keys.
+ + \ No newline at end of file diff --git a/advanced/how-to-debug-scriptcontext/index.html b/advanced/how-to-debug-scriptcontext/index.html index ad2ec32ad..986c1ddf2 100644 --- a/advanced/how-to-debug-scriptcontext/index.html +++ b/advanced/how-to-debug-scriptcontext/index.html @@ -4,13 +4,13 @@ How to Debug ScriptContext Failure | sCrypt - - + +
-

How to Debug ScriptContext Failure

ScriptContext enables the logic of the contract to be executed correctly according to the agreement, and the state of the contract to be propagated correctly.

When it runs incorrectly, you need to master the following methods to locate the error more efficiently.

hashOutputs assertion failed

The hashOutputs field of ScriptContext is the double SHA256 of the serialization of all output amount (8-byte little endian) with scriptPubKey. Through it, we can agree on how the outputs of the transaction calling the contract should be constructed.

If the output of the transaction is not constructed as required by the contract, then the hashOutputs of ScriptContext field will not match the the double SHA256 of the outputs produced in the code when the contract runs. The following assertion will fail:

assert(this.ctx.hashOutputs == hash256(outputs), 'hashOutputs mismatch')

We all know that if the preimage of the hash is inconsistent, the hash value will not match. When an assertion failure occurs, we can only see two mismatched hash values, and cannot visually see the difference between the preimages of the two hash values (that is, the outputs in the contract and the outputs of the transaction).

A function diffOutputs in DebugFunctions Interface is provided to directly compare the difference between the outputs argument and all the outputs of the transaction bound by this.to, which are serialized and hashed to produce the hashOutputs field of ScriptContext.

Just call this.debug.diffOutputs(outputs) in the contract:

this.debug.diffOutputs(outputs) // diff and print the comparison result
assert(this.ctx.hashOutputs == hash256(outputs), 'hashOutputs mismatch')

and you will see the comparison result:

diffoutputs

If the outputs of the transaction is inconsistent with the outputs expected by the contract:

  1. Outputs of the transaction is marked green.
  2. Outputs expected by the contract is marked red.
  3. Identical parts are marked in gray.

Through the printed comparison results, we can intuitively see that the number of satoshis included in the output calculated in the contract is different from the number of satoshis included in the output actually added when constructing the transaction. Now, we have found the source of the error.

- - +

How to Debug ScriptContext Failure

ScriptContext enables the logic of the contract to be executed correctly according to the agreement, and the state of the contract to be propagated correctly.

When it runs incorrectly, you need to master the following methods to locate the error more efficiently.

hashOutputs assertion failed

The hashOutputs field of ScriptContext is the double SHA256 of the serialization of all output amount (8-byte little endian) with scriptPubKey. Through it, we can agree on how the outputs of the transaction calling the contract should be constructed.

If the output of the transaction is not constructed as required by the contract, then the hashOutputs of ScriptContext field will not match the the double SHA256 of the outputs produced in the code when the contract runs. The following assertion will fail:

assert(this.ctx.hashOutputs == hash256(outputs), 'hashOutputs mismatch')

We all know that if the preimage of the hash is inconsistent, the hash value will not match. When an assertion failure occurs, we can only see two mismatched hash values, and cannot visually see the difference between the preimages of the two hash values (that is, the outputs in the contract and the outputs of the transaction).

A function diffOutputs in DebugFunctions Interface is provided to directly compare the difference between the outputs argument and all the outputs of the transaction bound by this.to, which are serialized and hashed to produce the hashOutputs field of ScriptContext.

Just call this.debug.diffOutputs(outputs) in the contract:

this.debug.diffOutputs(outputs) // diff and print the comparison result
assert(this.ctx.hashOutputs == hash256(outputs), 'hashOutputs mismatch')

and you will see the comparison result:

diffoutputs

If the outputs of the transaction is inconsistent with the outputs expected by the contract:

  1. Outputs of the transaction is marked green.
  2. Outputs expected by the contract is marked red.
  3. Identical parts are marked in gray.

Through the printed comparison results, we can intuitively see that the number of satoshis included in the output calculated in the contract is different from the number of satoshis included in the output actually added when constructing the transaction. Now, we have found the source of the error.

+ + \ No newline at end of file diff --git a/advanced/how-to-integrate-scrypt-service/index.html b/advanced/how-to-integrate-scrypt-service/index.html index 38c602412..7df1c2937 100644 --- a/advanced/how-to-integrate-scrypt-service/index.html +++ b/advanced/how-to-integrate-scrypt-service/index.html @@ -4,13 +4,13 @@ How to Integrate sCrypt Service | sCrypt - - + +
-
Skip to main content

How to Integrate sCrypt Service

Before interacting with a sCrypt contract, we must create a contract instance representing the latest state of the contract on chain. Such an instance can be created by calling the fromTx method. However, this means your application needs to track and record all contract-related transactions, especially for a stateful contract.

An easier alternative is to leverage sCrypt infrastructure service, which tracks such transactions, so you can focus on your application logic.

Get Your API Key

Step 1: Create Your Free Account

Go to the sCrypt homepage to create your free account.

Step 2: Get API Key

Sign in and click on the copy icon to copy your API Key.

Integration

Once you have an API key, you can easily integrate sCrypt service into your app by following these simple steps.

Step 1: Initialize Client

You can pass the API key, along with network, to the Scrypt.init function to initialize an sCrypt client in your app.

import { Scrypt, bsv } from 'scrypt-ts'

Scrypt.init({
apiKey: 'YOUR_API_KEY',
network: bsv.Networks.testnet,
})

Step 2: Connect ScryptProvider with your signer

Connect signer to ScryptProvider, the required provider to use sCrypt service.

const signer = new TestWallet(myPrivateKey)
await signer.connect(new ScryptProvider())

Step 3: Get Contract ID

Each contract is uniquely identified by the transaction that deploy it and the output it is in, which we regard as its ID.

const counter = new Counter(0n)
// connect signer
await counter.connect(signer)

const balance = 1
const deployTx = await counter.deploy(balance)
console.log('contract Counter deployed: ', deployTx.id)

const contractId = {
/** The deployment transaction id */
txId: deployTx.id,
/** The output index */
outputIndex: 0,
}

You can usually get the ID of a contract from its creator, who publicizes it so others can interact with it.

Step 4: Get Contract Instance

Once you have the contract ID, you can easily create a contract instance as follows.

const currentInstance = await Scrypt.contractApi.getLatestInstance(
Counter,
contractId
)

// connect signer
await currentInstance.connect(signer)

For a stateless contract, the instance points to the deployment tx; for a stateful one, it points to the latest tip in a chain of txs, which sCrypt service tracks automatically.

Interact with the Contract

Once you have the instance after following the steps above, you can easily read from the contract, write to it, and listen to it.

Read

You read an instance's properties using the dot operator, like any other object.

// read @prop count
console.log(counter.count)
note

Reading does NOT broadcast a transaction to the blockchain.

Write

To update a contract instance, you call its public method as before, which writes to the blockchain by broadcasting a transaction.

// call the method of current instance to apply the updates on chain
const { tx } = await currentInstance.methods.incrementOnChain()

console.log(`Counter contract called, tx: ${tx.id}`)

Listen to Events

Often, your app needs to be notified when a contract gets called and updated. It is essential to be able to listen to such events in real time that can alert your app whenever something relevant occurs on chain. For example, in your front-end, you can refresh the web page to show the user the latest state of a contract, upon event notifications.

With the sCrypt service, you can easily subscribe to a contract's events by its contract ID, using ethier websockets (client side) or webhooks (server side) per your requirements.

Websockets

To use websockets to listen for contract events, just use the Scrypt.contractApi.subscribe dedicated API in our client SDK, which takes two parameters:

  1. options: SubscribeOptions<T>: it includes a contract class, a contract ID, and a optional list of method names monitored.
interface SubscribeOptions<T> {
clazz: new (...args: any) => T;
id: ContractId;
methodNames?: Array<string>;
}

If methodNames is set, you will be notified only when public functions in the list are called. Otherwise, you will be notified when ANY public function is called.

  1. callback: (event: ContractCalledEvent<T>) => void: a callback funciton upon receiving notifications.

ContractCalledEvent<T> contains relevant information on how the contract is called:

  • methodName: string, which public method is called

  • args: SupportedParamType[], arguments the public method is called with

  • tx: bsv.Transaction, transaction where contract is called from

  • nexts: Array[T], includes the new contract instances created by this call. If a stateful contract is called, nexts contains the contract instances containing the new state generated by this call. You can read the latest state from the new contract instance to, e.g., display the new state to users. If a stateless contract is called, nexts is empty.

Below is an example of listening to events when incrementOnChain method is called.

const subscription = Scrypt.contractApi.subscribe({
clazz: Counter, // contract class
id: contractId, // contract id
methodNames: ['incrementOnChain']
}, (event: ContractCalledEvent<Counter>) => {
// callback when receiving a notification
console.log(`${event.methodName} is called with args: ${event.args}`)
});
note

When using this API, you do not need any backend services of your own; the code usually runs in your users' browsers. There is a security issue because of exposure of your API key. So it’s highly recommended that you just use it in demo projects for trusted users.

Webhooks

There is an alternative for listening to contract events in a more secure and effective way. Just use our webhook service to push event data to your own backend service.

Webhook Management

First, you need to create a valid webhook in our service before trying to receive any event data. You can manage webhooks on the webhooks page of our dashboard.

To create a valid webhook, you need to provide the following information:

  1. Webhook URL

This is the specified URL of your backend service for receving the associated event data.

  1. Network

A webhook can only receive events from a single network. It must be either testnet or mainnet.

  1. Contract ID

A webhook must listen to a certain contract ID. In other words, it will be notified only when this contract is called on chain.

Please note that the contract can only be listened to if it is deployed and called using our SDK or services.

  1. Contract Artifact

A contract artifact is also needed to decode call data on chain. You can usually find it in the artifact folder of your sCrypt project. It is required if the contract ID was newly registered to our service. It becomes optional if it has been registered before. Also, you can only update artifacts registered first by you.

Besides adding webhooks in dashboard, you can add them programmatically.


const fs = require('fs').promises;
const util = require('util');

// Async function to read a JSON file
async function readArtifactFromFile(filePath) {
try {
// Read the file using fs.promises.readFile and await for the result
const data = await fs.readFile(filePath, 'utf8');

// Parse the JSON data
const jsonData = JSON.parse(data);

// Return the parsed JSON object
return jsonData;
} catch (error) {
// Handle errors, e.g., file not found
throw new Error('Error reading JSON file: ' + error.message);
}
}


async function main() {
try {
// Provide the path to your JSON artifact file
const artifactFilePath = 'path_to_your_json_file.json';

// Fetch the JSON artifact data from the file
const artifact = await readArtifactFromFile(artifactFilePath);

const apiKey = '[Your API key]';
const webhookUrl = 'https://api.scrypt.io/webhooks/create'; // Use 'https://testnet-api.scrypt.io' for testnet

const requestBody = {
url: 'http://127.0.0.1:3005/api/webhooks/test_notify',
contractId: {
txId: "1fa604263d2a16f6292f788e391b83ea7037fb9eb2ed0055ab5802ab2d090ef5",
outputIndex: 0
},
desc: "test webhook",
artifact: artifact // Use the fetched artifact data here
};

const response = await fetch(webhookUrl, {
method: 'POST',
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`
},
body: JSON.stringify(requestBody)
});

if (!response.ok) {
throw new Error('Failed to create webhook');
}

const responseData = await response.json();
console.log(responseData);
} catch (error) {
console.error('Error:', error);
}
}

// Call the main function to start the process
main();

Webhook Request and Response

When a contract is called on chain, we will push event data through a http POST request with a body like this to your webhook URL:

{
"webhookId": "wh_EyY2zEnogmK9e57Q",
"createdAt": "2023-07-24T04:00:32.246Z",
"events": [{
"eventType": "utxoSpent",
"spentUtxo": {
"txId": "966a3fb5d46c673ceaef2a476e828b75a6e6eae28839b36c0ff42cddc7a28f5b",
"outputIndex": 0
},
"contractId": {
"txId": "966a3fb5d46c673ceaef2a476e828b75a6e6eae28839b36c0ff42cddc7a28f5b",
"outputIndex": 0
},
"spentBy": {
"txId": "c359669cef68509d8357741e57bdff29f731c28643596d2c49f12dcd633e89f7",
"inputIndex": 0
},
"createdInSpentTxOutputs": [
0
],
"id": "evt_6XnqNUIhoZJ6SaEg5sDGcC",
"methodName": "vote",
"args": [{
"name": "name",
"type": "bytes",
"value": "6950686f6e65"
}]
}]
}

The request details the events data:

  • eventType: The type name of the event. Currently only utxoSpent available.

  • spentUtxo: The specified utxo of the contract spent in the event.

  • contractId: The contract ID that the event belongs to.

  • spentBy: The specified input index of the contract call tx from which the event comes.

  • createdInSpentTxOutputs: Newly generated contract utxo(s) in the spent tx if it's a stateful contract.

  • id: Unique event id.

  • methodName: The method name of the contract call of the event.

  • args: The argument list of the contract call of the event.

You need to return a HTTP code of 200 for a successful acknowledgement. We will automatically pause the webhook after several unsuccessful deliveries. You need to manually reactivate it on the webhooks page before we start pushing notifications to it again. For a single event, there might be more than one notification pushed to the webhook, so make sure you have this situation handled.

Webhook Security

To keep your webhook requests secure, we add a signature header x-scrypt-signature for each request by signing the request data with your own API key using the HMAC-SHA256 algorithm. You can verify it if you want. It can be generated using code like this:

const signature = crypto.createHmac('sha256', apiKey).update(JSON.stringify(body)).digest('hex');
Webhook Limit

The number of webhooks that each user can create is limited. The following is the limit on the number of webhooks that users of different plans can create.

Planlimt on testnetlimt on mainnet
Starter1010
Pro100100
Business200200
Enterprise300300
- - +
Skip to main content

How to Integrate sCrypt Service

Before interacting with a sCrypt contract, we must create a contract instance representing the latest state of the contract on chain. Such an instance can be created by calling the fromTx method. However, this means your application needs to track and record all contract-related transactions, especially for a stateful contract.

An easier alternative is to leverage sCrypt infrastructure service, which tracks such transactions, so you can focus on your application logic.

Get Your API Key

Step 1: Create Your Free Account

Go to the sCrypt homepage to create your free account.

Step 2: Get API Key

Sign in and click on the copy icon to copy your API Key.

Integration

Once you have an API key, you can easily integrate sCrypt service into your app by following these simple steps.

Step 1: Initialize Client

You can pass the API key, along with network, to the Scrypt.init function to initialize an sCrypt client in your app.

import { Scrypt, bsv } from 'scrypt-ts'

Scrypt.init({
apiKey: 'YOUR_API_KEY',
network: bsv.Networks.testnet,
})

Step 2: Connect ScryptProvider with your signer

Connect signer to ScryptProvider, the required provider to use sCrypt service.

const signer = new TestWallet(myPrivateKey)
await signer.connect(new ScryptProvider())

Step 3: Get Contract ID

Each contract is uniquely identified by the transaction that deploy it and the output it is in, which we regard as its ID.

const counter = new Counter(0n)
// connect signer
await counter.connect(signer)

const balance = 1
const deployTx = await counter.deploy(balance)
console.log('contract Counter deployed: ', deployTx.id)

const contractId = {
/** The deployment transaction id */
txId: deployTx.id,
/** The output index */
outputIndex: 0,
}

You can usually get the ID of a contract from its creator, who publicizes it so others can interact with it.

Step 4: Get Contract Instance

Once you have the contract ID, you can easily create a contract instance as follows.

const currentInstance = await Scrypt.contractApi.getLatestInstance(
Counter,
contractId
)

// connect signer
await currentInstance.connect(signer)

For a stateless contract, the instance points to the deployment tx; for a stateful one, it points to the latest tip in a chain of txs, which sCrypt service tracks automatically.

Interact with the Contract

Once you have the instance after following the steps above, you can easily read from the contract, write to it, and listen to it.

Read

You read an instance's properties using the dot operator, like any other object.

// read @prop count
console.log(counter.count)
note

Reading does NOT broadcast a transaction to the blockchain.

Write

To update a contract instance, you call its public method as before, which writes to the blockchain by broadcasting a transaction.

// call the method of current instance to apply the updates on chain
const { tx } = await currentInstance.methods.incrementOnChain()

console.log(`Counter contract called, tx: ${tx.id}`)

Listen to Events

Often, your app needs to be notified when a contract gets called and updated. It is essential to be able to listen to such events in real time that can alert your app whenever something relevant occurs on chain. For example, in your front-end, you can refresh the web page to show the user the latest state of a contract, upon event notifications.

With the sCrypt service, you can easily subscribe to a contract's events by its contract ID, using ethier websockets (client side) or webhooks (server side) per your requirements.

Websockets

To use websockets to listen for contract events, just use the Scrypt.contractApi.subscribe dedicated API in our client SDK, which takes two parameters:

  1. options: SubscribeOptions<T>: it includes a contract class, a contract ID, and a optional list of method names monitored.
interface SubscribeOptions<T> {
clazz: new (...args: any) => T;
id: ContractId;
methodNames?: Array<string>;
}

If methodNames is set, you will be notified only when public functions in the list are called. Otherwise, you will be notified when ANY public function is called.

  1. callback: (event: ContractCalledEvent<T>) => void: a callback funciton upon receiving notifications.

ContractCalledEvent<T> contains relevant information on how the contract is called:

  • methodName: string, which public method is called

  • args: SupportedParamType[], arguments the public method is called with

  • tx: bsv.Transaction, transaction where contract is called from

  • nexts: Array[T], includes the new contract instances created by this call. If a stateful contract is called, nexts contains the contract instances containing the new state generated by this call. You can read the latest state from the new contract instance to, e.g., display the new state to users. If a stateless contract is called, nexts is empty.

Below is an example of listening to events when incrementOnChain method is called.

const subscription = Scrypt.contractApi.subscribe({
clazz: Counter, // contract class
id: contractId, // contract id
methodNames: ['incrementOnChain']
}, (event: ContractCalledEvent<Counter>) => {
// callback when receiving a notification
console.log(`${event.methodName} is called with args: ${event.args}`)
});
note

When using this API, you do not need any backend services of your own; the code usually runs in your users' browsers. There is a security issue because of exposure of your API key. So it’s highly recommended that you just use it in demo projects for trusted users.

Webhooks

There is an alternative for listening to contract events in a more secure and effective way. Just use our webhook service to push event data to your own backend service.

Webhook Management

First, you need to create a valid webhook in our service before trying to receive any event data. You can manage webhooks on the webhooks page of our dashboard.

To create a valid webhook, you need to provide the following information:

  1. Webhook URL

This is the specified URL of your backend service for receving the associated event data.

  1. Network

A webhook can only receive events from a single network. It must be either testnet or mainnet.

  1. Contract ID

A webhook must listen to a certain contract ID. In other words, it will be notified only when this contract is called on chain.

Please note that the contract can only be listened to if it is deployed and called using our SDK or services.

  1. Contract Artifact

A contract artifact is also needed to decode call data on chain. You can usually find it in the artifact folder of your sCrypt project. It is required if the contract ID was newly registered to our service. It becomes optional if it has been registered before. Also, you can only update artifacts registered first by you.

Besides adding webhooks in dashboard, you can add them programmatically.


const fs = require('fs').promises;
const util = require('util');

// Async function to read a JSON file
async function readArtifactFromFile(filePath) {
try {
// Read the file using fs.promises.readFile and await for the result
const data = await fs.readFile(filePath, 'utf8');

// Parse the JSON data
const jsonData = JSON.parse(data);

// Return the parsed JSON object
return jsonData;
} catch (error) {
// Handle errors, e.g., file not found
throw new Error('Error reading JSON file: ' + error.message);
}
}


async function main() {
try {
// Provide the path to your JSON artifact file
const artifactFilePath = 'path_to_your_json_file.json';

// Fetch the JSON artifact data from the file
const artifact = await readArtifactFromFile(artifactFilePath);

const apiKey = '[Your API key]';
const webhookUrl = 'https://api.scrypt.io/webhooks/create'; // Use 'https://testnet-api.scrypt.io' for testnet

const requestBody = {
url: 'http://127.0.0.1:3005/api/webhooks/test_notify',
contractId: {
txId: "1fa604263d2a16f6292f788e391b83ea7037fb9eb2ed0055ab5802ab2d090ef5",
outputIndex: 0
},
desc: "test webhook",
artifact: artifact // Use the fetched artifact data here
};

const response = await fetch(webhookUrl, {
method: 'POST',
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`
},
body: JSON.stringify(requestBody)
});

if (!response.ok) {
throw new Error('Failed to create webhook');
}

const responseData = await response.json();
console.log(responseData);
} catch (error) {
console.error('Error:', error);
}
}

// Call the main function to start the process
main();

Webhook Request and Response

When a contract is called on chain, we will push event data through a http POST request with a body like this to your webhook URL:

{
"webhookId": "wh_EyY2zEnogmK9e57Q",
"createdAt": "2023-07-24T04:00:32.246Z",
"events": [{
"eventType": "utxoSpent",
"spentUtxo": {
"txId": "966a3fb5d46c673ceaef2a476e828b75a6e6eae28839b36c0ff42cddc7a28f5b",
"outputIndex": 0
},
"contractId": {
"txId": "966a3fb5d46c673ceaef2a476e828b75a6e6eae28839b36c0ff42cddc7a28f5b",
"outputIndex": 0
},
"spentBy": {
"txId": "c359669cef68509d8357741e57bdff29f731c28643596d2c49f12dcd633e89f7",
"inputIndex": 0
},
"createdInSpentTxOutputs": [
0
],
"id": "evt_6XnqNUIhoZJ6SaEg5sDGcC",
"methodName": "vote",
"args": [{
"name": "name",
"type": "bytes",
"value": "6950686f6e65"
}]
}]
}

The request details the events data:

  • eventType: The type name of the event. Currently only utxoSpent available.

  • spentUtxo: The specified utxo of the contract spent in the event.

  • contractId: The contract ID that the event belongs to.

  • spentBy: The specified input index of the contract call tx from which the event comes.

  • createdInSpentTxOutputs: Newly generated contract utxo(s) in the spent tx if it's a stateful contract.

  • id: Unique event id.

  • methodName: The method name of the contract call of the event.

  • args: The argument list of the contract call of the event.

You need to return a HTTP code of 200 for a successful acknowledgement. We will automatically pause the webhook after several unsuccessful deliveries. You need to manually reactivate it on the webhooks page before we start pushing notifications to it again. For a single event, there might be more than one notification pushed to the webhook, so make sure you have this situation handled.

Webhook Security

To keep your webhook requests secure, we add a signature header x-scrypt-signature for each request by signing the request data with your own API key using the HMAC-SHA256 algorithm. You can verify it if you want. It can be generated using code like this:

const signature = crypto.createHmac('sha256', apiKey).update(JSON.stringify(body)).digest('hex');
Webhook Limit

The number of webhooks that each user can create is limited. The following is the limit on the number of webhooks that users of different plans can create.

Planlimt on testnetlimt on mainnet
Starter1010
Pro100100
Business200200
Enterprise300300
+ + \ No newline at end of file diff --git a/advanced/how-to-replay-instance/index.html b/advanced/how-to-replay-instance/index.html index b9667a94d..2f7b8afaa 100644 --- a/advanced/how-to-replay-instance/index.html +++ b/advanced/how-to-replay-instance/index.html @@ -4,13 +4,13 @@ How to Replay a Contract Instance to the Latest State | sCrypt - - + +
-
Skip to main content

How to Replay a Contract Instance to the Latest State

Using sCrypt Service and sCrypt client, we can effortlessly create a contract instance reflecting the latest state as follows:

const currentInstance = await Scrypt.contractApi.getLatestInstance(
Counter,
contractId
)

However, this method is ineffective for smart contracts with states of type HashedMap or HashedSet. This is because each instance only contains hashed values, not the original ones.

In this section, we'll use contract CrowdfundReplay located at src/contracts/crowdfundReplay.ts as a reference to explain how to replay these contract instances to their latest states.

This crowdfund contract features a HashedMap donators that records the donors' public key and their respective donation satoshi amounts.

export type Donators = HashedMap<PubKey, bigint>

export class CrowdfundReplay extends SmartContract {

@prop(true)
donators: Donators

...
}

This contract has three public methods:

  • donate adds an entry to the HashedMap.
  • refund removes a specific donator from the map.
  • collect destroys the contract without updating any stateful properties.
export type Donators = HashedMap<PubKey, bigint>

export class CrowdfundReplay extends SmartContract {
...

@method()
public donate(donator: PubKey, amount: bigint) {
...
assert(!this.donators.has(donator), 'donator already exists')
this.donators.set(donator, amount)
...
}

@method()
public refund(donator: PubKey, amount: bigint, sig: Sig) {
...
assert(this.donators.canGet(donator, amount), 'not donated before')
assert(this.donators.delete(donator), 'failed to remove donator')
...
}

@method()
public collect(sig: Sig) {
...
}
}

To replay the contract instance to the latest states, follow these three steps:

Step 1. Offchain Helper Functions

Initially, add helper functions that update stateful properties in a manner identical to the public methods.

These functions are defined within the offchainUpdates object:

class CrowdfundReplay extends SmartContract {

...

offchainUpdates: OffchainUpdates<CrowdfundReplay> = {
'donate': (next: CrowdfundReplay, donator: PubKey, amount: bigint) => {
next.donators.set(donator, amount)
},
'refund': (next: CrowdfundReplay, donator: PubKey) => {
next.donators.delete(donator)
},
}

...
}
note

The object keys must match the public method names precisely.

In our example, we only need two helper functions since the collect method doesn't alter any stateful properties.

Step 2. Create Instance from Deployment Tx

Retrieve the deployment transaction using the contract ID. Subsequently, recover the contract instance from it.

// Recover instance from the deployment transaction
const tx = await provider.getTx(contractId.txId)
const instance = CrowdfundReplay.fromTx(
tx,
contractId.outputIndex,
{
donators: new HashedMap<PubKey, bigint>(),
}
)

Note: For more details on the workings of the fromTx() and getTransaction() functions, refer to the documentation here.

Step 3. Replay Instance to Latest States

Invoke the replayToLatest function to acquire the latest contract instance.

import { replayToLatest } from 'scrypt-ts'

...

const latestInstance = await replayToLatest(instance, contractId)

if (latestInstance) {
// The latest instance is now ready for use.
...
}

Note: If the replayToLatest() function yields null, it indicates that there have been no state changes for the contract instance. This scenario arises if the contract hasn't been interacted with since its deployment or if all state modifications have been reverted.


- - +
Skip to main content

How to Replay a Contract Instance to the Latest State

Using sCrypt Service and sCrypt client, we can effortlessly create a contract instance reflecting the latest state as follows:

const currentInstance = await Scrypt.contractApi.getLatestInstance(
Counter,
contractId
)

However, this method is ineffective for smart contracts with states of type HashedMap or HashedSet. This is because each instance only contains hashed values, not the original ones.

In this section, we'll use contract CrowdfundReplay located at src/contracts/crowdfundReplay.ts as a reference to explain how to replay these contract instances to their latest states.

This crowdfund contract features a HashedMap donators that records the donors' public key and their respective donation satoshi amounts.

export type Donators = HashedMap<PubKey, bigint>

export class CrowdfundReplay extends SmartContract {

@prop(true)
donators: Donators

...
}

This contract has three public methods:

  • donate adds an entry to the HashedMap.
  • refund removes a specific donator from the map.
  • collect destroys the contract without updating any stateful properties.
export type Donators = HashedMap<PubKey, bigint>

export class CrowdfundReplay extends SmartContract {
...

@method()
public donate(donator: PubKey, amount: bigint) {
...
assert(!this.donators.has(donator), 'donator already exists')
this.donators.set(donator, amount)
...
}

@method()
public refund(donator: PubKey, amount: bigint, sig: Sig) {
...
assert(this.donators.canGet(donator, amount), 'not donated before')
assert(this.donators.delete(donator), 'failed to remove donator')
...
}

@method()
public collect(sig: Sig) {
...
}
}

To replay the contract instance to the latest states, follow these three steps:

Step 1. Offchain Helper Functions

Initially, add helper functions that update stateful properties in a manner identical to the public methods.

These functions are defined within the offchainUpdates object:

class CrowdfundReplay extends SmartContract {

...

offchainUpdates: OffchainUpdates<CrowdfundReplay> = {
'donate': (next: CrowdfundReplay, donator: PubKey, amount: bigint) => {
next.donators.set(donator, amount)
},
'refund': (next: CrowdfundReplay, donator: PubKey) => {
next.donators.delete(donator)
},
}

...
}
note

The object keys must match the public method names precisely.

In our example, we only need two helper functions since the collect method doesn't alter any stateful properties.

Step 2. Create Instance from Deployment Tx

Retrieve the deployment transaction using the contract ID. Subsequently, recover the contract instance from it.

// Recover instance from the deployment transaction
const tx = await provider.getTx(contractId.txId)
const instance = CrowdfundReplay.fromTx(
tx,
contractId.outputIndex,
{
donators: new HashedMap<PubKey, bigint>(),
}
)

Note: For more details on the workings of the fromTx() and getTransaction() functions, refer to the documentation here.

Step 3. Replay Instance to Latest States

Invoke the replayToLatest function to acquire the latest contract instance.

import { replayToLatest } from 'scrypt-ts'

...

const latestInstance = await replayToLatest(instance, contractId)

if (latestInstance) {
// The latest instance is now ready for use.
...
}

Note: If the replayToLatest() function yields null, it indicates that there have been no state changes for the contract instance. This scenario arises if the contract hasn't been interacted with since its deployment or if all state modifications have been reverted.


+ + \ No newline at end of file diff --git a/advanced/inline-asm/index.html b/advanced/inline-asm/index.html index ac27637e0..07c3c1705 100644 --- a/advanced/inline-asm/index.html +++ b/advanced/inline-asm/index.html @@ -4,14 +4,14 @@ Use Script inside sCrypt | sCrypt - - + +
-
Skip to main content

Use Script inside sCrypt

Script is a low-level language and acts as assembly for the Bitcoin Virtual Machine. Usually, developers do not have to deal with it directly and can use high-level languages like sCrypt. However, there are cases where using script is desirable. For example, customized script is optimized and thus smaller and more efficient than Script generated by sCrypt. Or script is generated using external tools like Baguette and needs to be integrated into sCrypt.

To achieve this currently, you have to edit the auto-generated .scrypt files under your project's artifacts directory.

First you create a project called P2PKH:

npx scrypt-cli project P2PKH --asm

Notice the --asm option must be enabled, meaning you are going to use inline assembly format of script.

Your contract is at src/contracts/p2pkh.ts:

export class P2PKH extends SmartContract {
@prop()
readonly address: Addr

constructor(address: Addr) {
super(...arguments)
this.address = address
}

@method()
public unlock(sig: Sig, pubkey: PubKey) {
assert(
pubKey2Addr(pubkey) == this.address,
'public key does not correspond to address'
)
assert(this.checkSig(sig, pubkey), 'signature check failed')
}
}

Say you want to substitute the unlock function with manual script, you edit the file .asm/asm.json.

{
"P2PKH": {
"unlock": "OP_DUP OP_HASH160 $pubKeyHash OP_EQUALVERIFY OP_CHECKSIG"
}
}

Variables can be defined by prefix $, as in $pubKeyHash.

We could also define multiple substitutions for multiple methods, if needed.

Now, you can compile the contracts with --asm option:

npx scrypt-cli compile --asm

Now, after compiling, the function body will be replaced with script, as could be seen in artifacts/P2PKH.scrypt.

Set Inline Assembly Variables

Assembly variables can be replaced with literal Script in ASM format using setAsmVars(). Each variable is prefixed by its unique scope, namely, the contract and the function it is under.

p2pkh = new P2PKH(Addr(myAddress.toByteString()))

// Set ASM variable
// Keep in mind that these are NOT constructor parameters and must be set separately.
asmVarValues = {
'P2PKH.unlock.address': myAddress.toByteString()
}
p2pkh.setAsmVars(asmVarValues)

Full code can be found on GitHub. +

Use Script inside sCrypt

Script is a low-level language and acts as assembly for the Bitcoin Virtual Machine. Usually, developers do not have to deal with it directly and can use high-level languages like sCrypt. However, there are cases where using script is desirable. For example, customized script is optimized and thus smaller and more efficient than Script generated by sCrypt. Or script is generated using external tools like Baguette and needs to be integrated into sCrypt.

To achieve this currently, you have to edit the auto-generated .scrypt files under your project's artifacts directory.

First you create a project called P2PKH:

npx scrypt-cli project P2PKH --asm

Notice the --asm option must be enabled, meaning you are going to use inline assembly format of script.

Your contract is at src/contracts/p2pkh.ts:

export class P2PKH extends SmartContract {
@prop()
readonly address: Addr

constructor(address: Addr) {
super(...arguments)
this.address = address
}

@method()
public unlock(sig: Sig, pubkey: PubKey) {
assert(
pubKey2Addr(pubkey) == this.address,
'public key does not correspond to address'
)
assert(this.checkSig(sig, pubkey), 'signature check failed')
}
}

Say you want to substitute the unlock function with manual script, you edit the file .asm/asm.json.

{
"P2PKH": {
"unlock": "OP_DUP OP_HASH160 $pubKeyHash OP_EQUALVERIFY OP_CHECKSIG"
}
}

Variables can be defined by prefix $, as in $pubKeyHash.

We could also define multiple substitutions for multiple methods, if needed.

Now, you can compile the contracts with --asm option:

npx scrypt-cli compile --asm

Now, after compiling, the function body will be replaced with script, as could be seen in artifacts/P2PKH.scrypt.

Set Inline Assembly Variables

Assembly variables can be replaced with literal Script in ASM format using setAsmVars(). Each variable is prefixed by its unique scope, namely, the contract and the function it is under.

p2pkh = new P2PKH(Addr(myAddress.toByteString()))

// Set ASM variable
// Keep in mind that these are NOT constructor parameters and must be set separately.
asmVarValues = {
'P2PKH.unlock.address': myAddress.toByteString()
}
p2pkh.setAsmVars(asmVarValues)

Full code can be found on GitHub. For more information about inline script/assembly, please refer to here.

note

Inline script bypasses many features of sCrypt such as type checking. Extreme caution has to be taken when using this advanced feature.

- - + + \ No newline at end of file diff --git a/advanced/sighash-type/index.html b/advanced/sighash-type/index.html index a1acc38d5..0e33b1307 100644 --- a/advanced/sighash-type/index.html +++ b/advanced/sighash-type/index.html @@ -4,17 +4,17 @@ Sighash Types | sCrypt - - + +
-

Sighash Types

A signature hash (sighash) flag is used to indicate which part of the transaction is signed by the ECDSA signature. There are mainly two ways to use it in the context of Bitcoin smart contracts.

1. Sighash Types in Signatures

In this section, we will go deep into the sighash type and introduce how to use it in the bitcoin signatures.

Digital Signature

A digital signature is a mathematical scheme that consists of two parts:

  • an algorithm for creating a signature, using a private key to sign a message.
sign(privateKey, message) --> signature
  • an algorithm that allows anyone to verify the signature, given also the message and a public key.
verify(signature, publicKey, message) --> true/false

The private key and the public key always appear in pairs, and the public key can be calculated from the private key, but not vice versa. Thus, you will always publish the public key so anyone can verify your signature, and keep the private key safe so only you can provide the correct signature.

Digital signatures are used to represent the authenticity and integrity of a message, since any modification to the message invalidates the signature, causing signature verification to fail. It is also proof that someone owns the private key, since the signature cannot be forged and it can be successfully verified with the corresponding public key only if it is signed with the correct private key.

Bitcoin Signature

Digital signatures are applied to messages, which in the case of bitcoin, are the transactions themselves. The signature implies a commitment by the signer to specific transaction data. In the simplest form, the signature applies to the entire transaction (excluding the unlocking scripts), thereby committing all the inputs, outputs, and other transaction fields. The P2PKH transaction is a simple example of using signatures, which is widely used in bitcoin.

Using a sighash flag, a Bitcoin signature specifies which parts of a transaction’s data is included and thus signed by a private key. The included transaction data is the so called ScriptContext. Every signature has a sighash flag and the flag can be different from signature to signature.

The image below illustrates what data would be signed using an ALL sighash flag. The data being signed is highlighted in green.

There are three sighash flags: ALL, NONE, and SINGLE.

Sighash flagDescription
ALLSignature applies to all inputs and outputs
NONESignature applies to all inputs, none of the outputs
SINGLESignature applies to all inputs but only the one output with the same index number as the signed input

In addition, there is a modifier flag ANYONECANPAY, which can be combined with each of the preceding flags. When ANYONECANPAY is set, only one input is signed, leaving the rest inputs open for modification.

Sighash flagDescription
ALL | ANYONECANPAYSignature applies to one input and all outputs
NONE | ANYONECANPAYSignature applies to one input, none of the outputs
SINGLE | ANYONECANPAYSignature applies to one input and the output with the same index number

All the six flags can be summarized in the following diagram.

As described in the doc before, different sighash type decides which part of the spending transaction is included in ScriptContext. More specifically, it will affect the value of four fields: hashPrevouts, hashSequence, hashOutputs, and sigHashType.

FieldDescription
hashPrevoutsIf the ANYONECANPAY modifier is not set, it's double SHA256 of the serialization of all input outpoints. Otherwise, it's a uint256 of 0x0000......0000.
hashSequenceIf none of the ANYONECANPAY, SINGLE, NONE is set, it's double SHA256 of the serialization of sequence of all inputs. Otherwise, it's a uint256 of 0x0000......0000.
hashOutputsIf the sighash type is neither SINGLE nor NONE, it's double SHA256 of the serialization of all outputs. If the sighash type is SINGLE and the input index is smaller than the number of outputs, it's the double SHA256 of the output with the same index as the input. Otherwise, it's a uint256 of 0x0000......0000.
sigHashTypesighash type of the signature

Use Cases

For a transaction signed with the default sighash ALL, it cannot be modified in any way. This is because the signature commits to all inputs and outputs of the transaction, if any part changes, the signature and thus the transactio becomes invalid. This is desirable in most cases, because the sender does not want others to temper with the signed transaction.

Let’s look at some examples using non-default sighash types.

Crowdfunding

Someone attempting to raise funds can construct a transaction with a single output. The single output pays a target amount to a fundraiser. Such a transaction is obviously invalid, as it has no inputs. Others can amend it by adding an input of their own, as a donation. They sign their own input with ALL|ANYONECANPAY and pass the partially signed transactions to the next donor. ALL ensures the output and thus the target and fundraiser cannot be modified. ANYONECANPAY ensures anyone can pay by adding new inputs without invalidating existing donors' signatures. Each donation is a "pledge" which cannot be collected by the fundraiser until the entire target amount is raised.

Blank Check

Someone attempting to write a blank check can construct a transaction with several inputs and no output, and sign all the inputs with NONE. The signatures only commit to inputs of the transaction. This allows anyone to add their desired outputs to the transaction to spend the funds in anyway she wants.

How to generate a signature with a specific sighash

For those contract public methods that require one or more signatures as input parameters, we can specify different sighash types for the signatures when calling it.

Take the P2PKH contract as an example, it requires a single signature to unlock.

@method()
public unlock(sig: Sig, pubkey: PubKey) {
// Check if the passed public key belongs to the specified address.
assert(pubKey2Addr(pubkey) == this.address, 'public key does not correspond to address')
// Check signature validity.
assert(this.checkSig(sig, pubkey), 'signature check failed')
}

There are two changes to specify a sighash type, which defaults to ALL if not specified explicitly.

  1. Pass a SignatureOption object to pubKeyOrAddrToSign to specify the sighash type.
  2. Pass the sighash as the third parameter of findSig().

Let's examine a usage example. Suppose we have the aforementioned P2PKH contract deployed, and we wish to call or unlock it. +

Sighash Types

A signature hash (sighash) flag is used to indicate which part of the transaction is signed by the ECDSA signature. There are mainly two ways to use it in the context of Bitcoin smart contracts.

1. Sighash Types in Signatures

In this section, we will go deep into the sighash type and introduce how to use it in the bitcoin signatures.

Digital Signature

A digital signature is a mathematical scheme that consists of two parts:

  • an algorithm for creating a signature, using a private key to sign a message.
sign(privateKey, message) --> signature
  • an algorithm that allows anyone to verify the signature, given also the message and a public key.
verify(signature, publicKey, message) --> true/false

The private key and the public key always appear in pairs, and the public key can be calculated from the private key, but not vice versa. Thus, you will always publish the public key so anyone can verify your signature, and keep the private key safe so only you can provide the correct signature.

Digital signatures are used to represent the authenticity and integrity of a message, since any modification to the message invalidates the signature, causing signature verification to fail. It is also proof that someone owns the private key, since the signature cannot be forged and it can be successfully verified with the corresponding public key only if it is signed with the correct private key.

Bitcoin Signature

Digital signatures are applied to messages, which in the case of bitcoin, are the transactions themselves. The signature implies a commitment by the signer to specific transaction data. In the simplest form, the signature applies to the entire transaction (excluding the unlocking scripts), thereby committing all the inputs, outputs, and other transaction fields. The P2PKH transaction is a simple example of using signatures, which is widely used in bitcoin.

Using a sighash flag, a Bitcoin signature specifies which parts of a transaction’s data is included and thus signed by a private key. The included transaction data is the so called ScriptContext. Every signature has a sighash flag and the flag can be different from signature to signature.

The image below illustrates what data would be signed using an ALL sighash flag. The data being signed is highlighted in green.

There are three sighash flags: ALL, NONE, and SINGLE.

Sighash flagDescription
ALLSignature applies to all inputs and outputs
NONESignature applies to all inputs, none of the outputs
SINGLESignature applies to all inputs but only the one output with the same index number as the signed input

In addition, there is a modifier flag ANYONECANPAY, which can be combined with each of the preceding flags. When ANYONECANPAY is set, only one input is signed, leaving the rest inputs open for modification.

Sighash flagDescription
ALL | ANYONECANPAYSignature applies to one input and all outputs
NONE | ANYONECANPAYSignature applies to one input, none of the outputs
SINGLE | ANYONECANPAYSignature applies to one input and the output with the same index number

All the six flags can be summarized in the following diagram.

As described in the doc before, different sighash type decides which part of the spending transaction is included in ScriptContext. More specifically, it will affect the value of four fields: hashPrevouts, hashSequence, hashOutputs, and sigHashType.

FieldDescription
hashPrevoutsIf the ANYONECANPAY modifier is not set, it's double SHA256 of the serialization of all input outpoints. Otherwise, it's a uint256 of 0x0000......0000.
hashSequenceIf none of the ANYONECANPAY, SINGLE, NONE is set, it's double SHA256 of the serialization of sequence of all inputs. Otherwise, it's a uint256 of 0x0000......0000.
hashOutputsIf the sighash type is neither SINGLE nor NONE, it's double SHA256 of the serialization of all outputs. If the sighash type is SINGLE and the input index is smaller than the number of outputs, it's the double SHA256 of the output with the same index as the input. Otherwise, it's a uint256 of 0x0000......0000.
sigHashTypesighash type of the signature

Use Cases

For a transaction signed with the default sighash ALL, it cannot be modified in any way. This is because the signature commits to all inputs and outputs of the transaction, if any part changes, the signature and thus the transactio becomes invalid. This is desirable in most cases, because the sender does not want others to temper with the signed transaction.

Let’s look at some examples using non-default sighash types.

Crowdfunding

Someone attempting to raise funds can construct a transaction with a single output. The single output pays a target amount to a fundraiser. Such a transaction is obviously invalid, as it has no inputs. Others can amend it by adding an input of their own, as a donation. They sign their own input with ALL|ANYONECANPAY and pass the partially signed transactions to the next donor. ALL ensures the output and thus the target and fundraiser cannot be modified. ANYONECANPAY ensures anyone can pay by adding new inputs without invalidating existing donors' signatures. Each donation is a "pledge" which cannot be collected by the fundraiser until the entire target amount is raised.

Blank Check

Someone attempting to write a blank check can construct a transaction with several inputs and no output, and sign all the inputs with NONE. The signatures only commit to inputs of the transaction. This allows anyone to add their desired outputs to the transaction to spend the funds in anyway she wants.

How to generate a signature with a specific sighash

For those contract public methods that require one or more signatures as input parameters, we can specify different sighash types for the signatures when calling it.

Take the P2PKH contract as an example, it requires a single signature to unlock.

@method()
public unlock(sig: Sig, pubkey: PubKey) {
// Check if the passed public key belongs to the specified address.
assert(pubKey2Addr(pubkey) == this.address, 'public key does not correspond to address')
// Check signature validity.
assert(this.checkSig(sig, pubkey), 'signature check failed')
}

There are two changes to specify a sighash type, which defaults to ALL if not specified explicitly.

  1. Pass a SignatureOption object to pubKeyOrAddrToSign to specify the sighash type.
  2. Pass the sighash as the third parameter of findSig().

Let's examine a usage example. Suppose we have the aforementioned P2PKH contract deployed, and we wish to call or unlock it. However, we encounter an issue: we don't possess sufficient funds to cover the network fees for the new contract call transaction. Fortunately, a generous friend offers to cover these fees for us. In this scenario, we can employ the ANYONECANPAY | ALL flag with our signature to unlock the deployed P2PKH contract. This allows our friend to append another input to our transaction, contributing funds to pay the network fee.

To illustrate, we would structure the contract call as follows:

const sighashType = SignatureHashType.ANYONECANPAY_ALL
const { tx } = await p2pkh.methods.unlock(
// Pass the first parameter, the signature, to `unlock`.
// Once the transaction is signed, signatures are returned in `SignatureResponse[]`.
// Identify the required signature(s) using the public key, address, and the sighash type specified.
(sigResps) => findSig(sigResps, publicKey, sighashType),
PubKey(toHex(publicKey)),
{
// Direct the signer to use the private key associated with `publicKey` and the specified sighash type to sign this transaction.
pubKeyOrAddrToSign: {
pubKeyOrAddr: publicKey,
sigHashType: sighashType,
},
// This flag ensures the call tx is only created locally and not broadcasted.
partiallySigned: true,
// Prevents automatic addition of fee inputs.
autoPayFee: false,
} as MethodCallOptions<P2PKH>
)

Executing the above will yield the entire contract call transaction without broadcasting it. We can subsequently pass this transaction to our friend. Since we applied the ANYONECANPAY sighash flag, adding an additional input will not invalidate our signature. This is because network nodes will exclusively use the first input to authenticate our signature.

To further elaborate, we might also use the ANYONECANPAY | SINGLE flag. This would grant our friend the capability to append extra outputs to our transaction. This can be advantageous, for instance, if he wishes to reclaim a portion of his contributed funds as change, especially if he used an UTXO with an excessive amount of locked-in funds.

You can find a full code example in our project boilerplate.

2. Sighash Types in @method() Parameters

In this section, we will introduce how to specify different sighash types in the @method() decorator.

note

Sighash here only affects contracts that access ScriptContext in their public methods.

Counter

Let us use the Counter contract as an example. It simply records how many times it has been called since deployment.

Noted that the @method decorator takes a sighash type as a parameter, whose default is ALL. According to the doc, hashOutputs is the double SHA256 of the serialization of all outputs when the sighash type is ALL. The default calling transaction builder adds a change output when necessary. That's why we need to add a change output when building outputs of the spending transaction in the public method: we need to build all the outputs that are included in hashOutputs. Otherwise, contract call will fail.

The following transaction is a contract calling transaction of Counter. As you can see, it contains two outputs: one for the new state, the other for change.

Advanced Counter

Noted that in the state transition of Counter, there is always only one UTXO that contains the latest contract state. When the contract is called, it spends the UTXO of the current state and creates a UTXO of the new state. Moreover, the contract input index of the spending transaction and the contract output index are the same.

In fact, we only care about the contract-related UTXO in the transaction inputs and outputs when calling Counter, and do not care about other inputs and outputs. Thus, we can use SINGLE | ANYONECANPAY to simplify the contract. SINGLE lets us focus on the contract output itself. ANYONECANPAY allows anyone to add inputs for this contract calling transaction to, e.g., pay fees.

We make two changes to the original Counter.

  1. Using @method(SigHash.ANYONECANPAY_SINGLE)
  2. Build an output that only contains the contract's new state, without the change output.
export class AdvancedCounter extends SmartContract {
...

// 1) add ANYONECANPAY_SINGLE
@method(SigHash.ANYONECANPAY_SINGLE)
public incrementOnChain() {
...

const amount: bigint = this.ctx.utxo.value
// 2) remove change output
const output: ByteString = this.buildStateOutput(amount)
assert(this.ctx.hashOutputs == hash256(output), 'hashOutputs mismatch')
}

...
}

You can check the complete code here.

The following transaction is a contract calling transaction of AdvancedCounter. You can see it also contains two outputs, but we only use one output when checking if it hashes to hashOutputs in the public method, since we use SINGLE.

More examples

Use different sighash types in @method() decorator will change the value of ScriptContext. This is useful in many cases.

  • If your contract needs to restrict all inputs and outputs of the spending transaction, use ALL.
  • If your contract is stateful and the state is always in a single output, simplify it using SINGLE.
  • If you want to enable someone else could add inputs after the transaction is sealed, such as for paying transaction fees, apply the ANYONECANPAY modifier.

You can find these examples in our boilerplate.

- - + + \ No newline at end of file diff --git a/advanced/timeLock/index.html b/advanced/timeLock/index.html index e21ed3950..f6b02c997 100644 --- a/advanced/timeLock/index.html +++ b/advanced/timeLock/index.html @@ -4,15 +4,15 @@ Time Lock | sCrypt - - + +
-

Time Lock

Overview

In this section, we will go over how to create a smart contract, which has a public method, that can only be unlocked once a certain point in time has passed.

What is a time lock?

In the context of smart contracts, a time-lock is a feature that restricts the spending of specific bitcoins until a specified future time or block height is reached. sCrypt offers capabilities to implement these types of time-locks in your smart contracts, providing a mechanism to ensure a transaction won't be included in a block before a certain point in time or block height is reached. In other words, the smart contract's method cannot be successfully invoked until that point in time has passed.

For instance, this mechanism could be used to add a withdrawal method to a smart contract. In the event of non-cooperation from other parties, an individual could retrieve their funds locked in the smart contract after some amount of time has passed. This approach is utilized in cross-chain atomic swaps, for example.

+

Time Lock

Overview

In this section, we will go over how to create a smart contract, which has a public method, that can only be unlocked once a certain point in time has passed.

What is a time lock?

In the context of smart contracts, a time-lock is a feature that restricts the spending of specific bitcoins until a specified future time or block height is reached. sCrypt offers capabilities to implement these types of time-locks in your smart contracts, providing a mechanism to ensure a transaction won't be included in a block before a certain point in time or block height is reached. In other words, the smart contract's method cannot be successfully invoked until that point in time has passed.

For instance, this mechanism could be used to add a withdrawal method to a smart contract. In the event of non-cooperation from other parties, an individual could retrieve their funds locked in the smart contract after some amount of time has passed. This approach is utilized in cross-chain atomic swaps, for example.

-Image Credit: bcoin

Implementation

In sCrypt, a time-lock can be enforced by constraining the locktime and sequence values of the script execution context. This context pertains to the execution of the transaction, which includes a call to the smart contract's public method. Thus, if the value is constrained – for example, the locktime needs to be above the value 1690236000 (a Unix timestamp) – then this transaction cannot be included into the blockchain until that point in time.

Note that the value of locktime can either be a Unix timestamp or a block height. For this value to be enforced, sequence also needs to be set to a value less than 0xffffffff.

sCrypt offers a convenient built-in function timeLock to enforce this constraint.

// Time after which our public method can be called.
@prop()
readonly matureTime: bigint // Can be a timestamp or block height.

// ...

@method()
public unlock() {
// The following assertion ensures that the `unlock` method can
// not be successfully invoked until `matureTime` has passed.
assert(this.timeLock(this.matureTime), 'time lock not yet expired')
}

It is important to note that this mechanism can be employed solely to ensure that a method can be called after a specific point in time. In contrast, it cannot be employed to ensure that a method is called before a specific point in time.

Calling

Upon a method call to the unlock method defined above, we need to set the locktime value of the transaction that will call the public method. We can do this by simply setting the locktime paramater of MethodCallOptions.

timeLock.methods.unlock(
{
lockTime: 1673523720
} as MethodCallOptions<TimeLock>
)

Internally this will also set the inputs sequence to a value lower than 0xffffffff. We can also set this value explicitly.

timeLock.methods.unlock(
{
lockTime: 1673523720,
sequence: 0
} as MethodCallOptions<TimeLock>
)

Lastly, if we are using a custom transaction builder we need to set these values for the unsigned transaction that we are building there.

instance.bindTxBuilder('unlock',
async (
current: TimeLock,
options: MethodCallOptions<TimeLock>
) => {

// ...

if (options.lockTime) {
unsignedTx.setLockTime(options.lockTime)
}
unsignedTx.setInputSequence(0, 0)

// ...
}
)

How does it work?

Under the hood, the timeLock function asserts that the sequence value of our calling transaction is less than UINT_MAX. This ensures that the Bitcoin network will enforce the locktime value.

Next, it checks if our target time-lock value indicates a block height or a Unix timestamp. If it's using a block height, i.e. the time-lock value is less than 500,000,000, the method also ensures that the locktime value of the calling transaction corresponds to a block height.

Lastly, the method verifies that the value of locktime is greater than or equal to the time-lock we have passed as an argument.

For more information on how the locktime and sequence values work, please read the BSV wiki page.

- - +Image Credit: bcoin

Implementation

In sCrypt, a time-lock can be enforced by constraining the locktime and sequence values of the script execution context. This context pertains to the execution of the transaction, which includes a call to the smart contract's public method. Thus, if the value is constrained – for example, the locktime needs to be above the value 1690236000 (a Unix timestamp) – then this transaction cannot be included into the blockchain until that point in time.

Note that the value of locktime can either be a Unix timestamp or a block height. For this value to be enforced, sequence also needs to be set to a value less than 0xffffffff.

sCrypt offers a convenient built-in function timeLock to enforce this constraint.

// Time after which our public method can be called.
@prop()
readonly matureTime: bigint // Can be a timestamp or block height.

// ...

@method()
public unlock() {
// The following assertion ensures that the `unlock` method can
// not be successfully invoked until `matureTime` has passed.
assert(this.timeLock(this.matureTime), 'time lock not yet expired')
}

It is important to note that this mechanism can be employed solely to ensure that a method can be called after a specific point in time. In contrast, it cannot be employed to ensure that a method is called before a specific point in time.

Calling

Upon a method call to the unlock method defined above, we need to set the locktime value of the transaction that will call the public method. We can do this by simply setting the locktime paramater of MethodCallOptions.

timeLock.methods.unlock(
{
lockTime: 1673523720
} as MethodCallOptions<TimeLock>
)

Internally this will also set the inputs sequence to a value lower than 0xffffffff. We can also set this value explicitly.

timeLock.methods.unlock(
{
lockTime: 1673523720,
sequence: 0
} as MethodCallOptions<TimeLock>
)

Lastly, if we are using a custom transaction builder we need to set these values for the unsigned transaction that we are building there.

instance.bindTxBuilder('unlock',
async (
current: TimeLock,
options: MethodCallOptions<TimeLock>
) => {

// ...

if (options.lockTime) {
unsignedTx.setLockTime(options.lockTime)
}
unsignedTx.setInputSequence(0, 0)

// ...
}
)

How does it work?

Under the hood, the timeLock function asserts that the sequence value of our calling transaction is less than UINT_MAX. This ensures that the Bitcoin network will enforce the locktime value.

Next, it checks if our target time-lock value indicates a block height or a Unix timestamp. If it's using a block height, i.e. the time-lock value is less than 500,000,000, the method also ensures that the locktime value of the calling transaction corresponds to a block height.

Lastly, the method verifies that the value of locktime is greater than or equal to the time-lock we have passed as an argument.

For more information on how the locktime and sequence values work, please read the BSV wiki page.

+ + \ No newline at end of file diff --git a/assets/images/close-f098212d4d8bfc7f2ae820ba5762125f.jpg b/assets/images/close-f098212d4d8bfc7f2ae820ba5762125f.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2a7a6221da4b79f88671b6b2aff90388fc678621 GIT binary patch literal 11416 zcma*MV{|4#xUT)iwr$(Ct%)YKJ+W;}l8J5GwryJz+sS)o@3Z&!?Q?#et5$X0RqKAb zdR0BWdUdy|jHF}&JpiC7A*!sQ%&i3r005x>RXK3LI{@%+g!qyU06<;Gr!sHcQ<-Th1x!pwYbVw#{|25Uq0Ml z4c-j)zU}>W_V zAk%m3x6Q}u8`6itmH$8gr{=fGckipxb8eg85>OBb2Xy#!_(0kus#7`^TJAmc4+Kg8 zH^0LFS%Ka}z^^vHbARBA>{k`=n>)|_{~cBhlQ5p2mBYdG=$l2Jn9^Mjkk(!+!?-3u`gXe>Fjz0kmzP zvS45TKeO~IWg~ngLcrzuB`D;h2AbTf4VL{IQDus@8a+N;`p^S0A>s@yBQ1DcN+m9loX>m%oO~_&Q`5{t_9oLPj2%-Sgwu0Mtmp^c2t)8Ym{Dku-N%zK?A#Bx9~2c_kIq0h+Z^S%wgy>P9k{{ zVt#{xc$LY?#+L@-ID(~I8*d9j(4WBeyD1NIGHa;_h7GRiGGUN%!cBxq$cIZh9jR6P z7i|RUI>?v=I-vHm>-x~}iP_8666aNrkt_OMuKYq*mkqEiYJ3N&klclQ>V_&gSLWk6 zPxikW$yip12D|vKzgo4>A1o_D#jQ-|h#|BlO>;GZq_upB7P!}^#9Af9hkj6ROq#Yc zU~Q_tNEMirtJB`CJm$7nTd2ftaOWSSn1_Po}rD_qv2%FGVEmcU9 zM^XVxae@q!&Bh+AJJq}df^B(R(V9DGKGBVN!xV;RbhT6CM&ig_-D_Lep2MW zoC>>p?B*yFi9I8DppJsv8@;LrF6XsjBHucfFuAZg>&IKoSKHg$k8CT#r>5dO(7FpN zL)J|WOyI!mI(tKZ@cOxI=O2oWdn1;IFBS!zoo#&AypN%8+sLw)dgOnHS6C>~cNR5g z!}EiIxJcc(3l!0Tbl0<`{^DrikR`-b+cf#<|AA+V7V-CSSPh)h<&`s6^-Dv zO^yZ&65v46tFq|X(_vP{eMA>-IcI{cFQ9_}E*pTrp`9~H+?40)4LR;Y=10B9Sit%JEYAMms2*F>{SoxF}7#>Gib5PoV6{HQ({yN4A&$p-_2+~^51ty&+NrveAep9?9|TV>EA`_I zLGN5k)tVw9qB1bPr#IM?K`}pQLRNk)PGy?|17%*iy4&ca2O%3%%3i*4>*_R$DjAFP zd{Fs1>Q%ls=|tYteAW^nLpWn#`T#@~C$c}^wmfwcMyTviM6**Y33UMgn+~Hp5&t}z zC3ta>N;mZ#Efm$ROV1a*R&q~Yv35e@hj1EHBcWGrSbp_ILJFJwd>L`ZN{t8Eiu&%D56+OmjP(3P27EN5(TcAi&) z6I94IN8|QwQFY0CIQW~^hJ)4CmlMm?v@KR@M|&o#cnQ~FJGm$;4A@p&Xn(3sfG(i(9$pi_DZ>`?PYp6 zL|4zQ#(No4yMSeqG}r+`+;oS3Wk)zc6xI*0z(t+z9>&((G)5pL2?=nJ3xsjlEz1xX zOJ!Ez7{6^ul98bks6$yJTr+J62d(9cTjw7MT`1%cDb~0c-BtsiZ^j#9@~piF7Jd}ChywxI%X@fR z44!`wj_+{6FV_0Y!}X(g-*Ohj+Ef%1sur@^xsV2nZE>YzA4b6DNN~@PE1rDbyb^v^ zSqpIe86n!64*h-oiYxwbNs?W&o7Q07vJT4rVy*TxTckU0fhRAHoIdWIEQH4nO4g>^ z$i&3NeQFm&UJMWTQL*QrX}u7S$K`DRs0RmnEyotzMyE=5ph9js{LETpssat5 z^d``56SIwHw4VOqKct`^V{*T(-zlqTGd&dT{A>5!rNfNQ<%n}r@eGqd?va9FFIfGE zvu&3_Z2>yNMYG?_F}0Q-XH~RNKXtGUDsm;gQU@#~CM*G2LNs^&Vfv&{D|8<}2?VW% zaFrxDi=ij-LD@Ab;0Gl`hL`ky_@3E=Bf_>};HMXT$l|6^y~V3Ap1(PG75wi4Zn{Aw zd|-t#!__>1rRdJ?JaObH(W2;QAC6w>BJ5l+Ec31bNQ;fGmSY(=>GG6L7`U(<-t0GN zutdg4frMtqBm_veIP$H*U~}V(B3l5-7{f8#~*ryCQ)y%C;xBjF$r}G9U#@{ ztC-zGr9Q&N6Uko;#;45o!}1ZU;%?@a-SC4D7f%16xHccbQdZ9G?A>4jprVviURYk+ z6}IxMhO#67xDK?;{!oWA_+4w9qRTUT>PsHaQC|g6av@@hT*uv0(a>I&3kjO|ckLSl zsv%8|Vg3Oxy+EwU&WQ*CPC2wQ#5mIJZBQxp#-^6i4DcqPT3MzfK*X+*AHnm{0cJQ6 z2D8BxoKV`7H@IM`IlDlft2?FMu@%Cz7=#46vV_V(7cLreQ6W;hX}hm3BEA2scla0G zuoJx_I5RmpazbIQus=#&zCe8j7Hz3RfoBt0WWl*!vd;smKT&9u4k7DcFgS@*c{%YL zcdP9)1q*gKXE~S8Y2W=1$!93$t8L^vl(o-zc&qc`dm%H$?JfvJ=|u-OGBjfMAahaH zujieY$F%FY(CdqCNsFC0d{uX@uE9>ytlxtmM8Ul8AVp$MBWmWtt_QO5fJL|quylU{ ziPu}+icjtPsv~Xm@FF)d#-d_~&u9|S+TBT-W(^o)vpDTguqg_mRaNK(;;xwxdB^l< z3y9{_?3pWtUV`C20e@H9Ae*xH6H4-rO|@(i0ukg*@8EX>4Y#{}IiFwOopzMM+vz{4 z+vldjQJI3h*U;(`-4fZWJwuY3n7~iNVS(c!c-u>IH3) z%^-;=^-u(ZsYviNR_s_y;kHXc*Iw|k(^gzhndoKHT#yor7^(6j?oJr^Gd7T0=%MG$ zvle0@9~+eLHAYySSu@zeu_Z$glCb*0VL6J7x&C-Pc~KLQ$t?Pz7*@jJs7p?pDv)3q zYZl&W^jb>dD4B|l(QN`fdK@1 zVtT!kfHMR+?)-DYf3Tkcj-LiD<$6^PHZPi`ma&V&#paAD&F?U8?PUm9NFW=Te=BJg zQ(YmlTsdA>Vr0Ka^KosJ@$t&MsRl$?rXt%zV!S-=f@`<+e!jF*^{6df749?MzZcqGM__-4~n!3$UfTd|J7`BCyz zwek}+4>Gx-s-|FvjCsYK9TxBKW&X|7%PU%h2S~EjZS^rdo4#pXZX4ps>5@Oe=m}wG z7td%3=ZE<*D0U!>vOi1A&Mr|hIF93-+&rLzu6WyPa6+idbRh}x|BO~ZKxWU>t6gErFo2F>~ zo6|Q99?F6r1T>ZOm(SNc^u+-P5!+BjxiPvazfjiOhxnLSF!yfK0AHB`+kU7-D^KGi zWuvxxd6_sS=$dh~BQ)Fy%t#%gmcBInI+K2aZLSOptE_x7>PdS_#%NETVCMh}0w=*_ubHdw!vV--TfU4#-D zcyJ*VfN|7hTgpTaqEUt&9dadPMye>c`1)rk_l$J&OHZM!n$bM?hLh&H)e$#7 zZV`U5R82E!f9v=g$_QD*jyIy=<3dgypd4JA>`V4-=L~UkJ}v>QRUW2sRgFlej|t{d zi(5zCB4|~$@Nwc?q>?yRq}DPcBdoG$vxsN`orDncM7W5gkEZpsL|aZAS=qGQa;qa9dEk;}G+{PCc zZk=S)1R*Y$kkSymGgmHfYUO{O8k>X8<3xP4mP4OHsS4_IB>sExE=&#g@O{gn$=s*6 zm42y4yN9rb4~b^V-90$%Z`;a5EA8WUrYm3^NG&6Fe9#hh1TgS3ZW-EMHLzJm;BWpw z{%o!iIlMRg+J>alIo}h2tAUv#(%DmPBlp-X7rEL=$7@G1Jsv%9F}uwDhNropgSo?_b;M+s@U(Yv3_C6|o6UrNIXLNpDw z+0&e!dn;#k0TaQ0TvvU+*S*!j2T!TI`sH|8>ywGKBsbQ~Uo`+gfYWhRF4IZNO6RtwHTQg} zJj?DX3Ud$8YycA)G+< zfwPO7(i(kbO*`DEMn~^&kvF=0_3QhiVdwp6a$WtJir!#&g8IYu>ZG~G@AuaBu)w3~ zTQ(M^vuZWDfe)MM7oB-1NkD=b>1G!pS->lDWaF-BZBsqE!@WxKi`F{}qT+9|&G>Ca zfIbA3UZf^CQzSuY;&RUsQ~f|kD#lC7B|Gv@=G{^5PZB}d2Ef1XTb?x#Q@5;TeTY9> z=iDAV3?iFjDxbM|huVv4!5xY*)_7OYSgoMs+`Eq-j`0Vul~47j%_@8wu!CEB|GX+N z6jV{NDaa2LLhNmW1ZrxG#PKB`ecL~xsOhzBw97jXVU9R_nF!)va;9oPy0IHYlm`zn z(Mwx7+gscmnu!h?ERDmxQ`~G;5Oom}=G>z$q;jd4Cno#EcS;xOO1{Y}d z3ueLc;e2mhYa|q@N0%%X5^rFl{B`B3x3ddG+Z;0U`_E2}(tHwP82Q#mV6h%jC2t#6 zg=3rLPWu)?IJ!E^4b3jTvo{_G9(4HvQNC@bZ+(I-mxD%CPwq^VYGT}g&&H6y-pdEC z($w;e&w;LR=Of;>7neY8is#5|Vr=CK{^wvjuxm2(&@;*`nVXkDm#ZG%=|$!pg@%$F zJFn+8IJ=6Pl=|YB)PUP>K#)=%aw|cbfh{UcbLG-EgyUSQn5UDb78TNsxd804>U~S+ z4chj4rTwoGStGPeD-AjUSpGql;#YK7t)BV?Sau$0(F}WPCrak!^`mNxNSj5uA}hOP z;g#PVQMNZnsX>AD%RH{VburqdAhj!lg&uaz`Uk)LUex>3W;^@gi5gq@C(pwhRVil+ z4juh~2Lvk!-tuGtQ%Ss@3`;cC&P`!qE9!*2k$R)b7AQ{i&ES)xeYABV;!ST_g)01} zAH%3S72L49n25Rl)*6rx4P}@O1c>we{FI*D)X)MreOu~4RY0DyN4tsL=~gxs3?^G|&!aVuL$(ORb2R1Fxs!k~ucdYAH%chZN^oFt{yYh0fHh0e zpQ_6vtskJcji%+rbzyO(5N(A=!f6YexuvN`?#tRs$0J5`KzC!LVJ^D7 zIPC?0Lvo2KU^PI{E8APo2Fr1m+BcWyE+SDppdHbGW~YI;lS1RfxH&ClIdE&Gg#APq zZFJE}!BMge;{$b>Uid@Akd*ka+L@zHWd>Rf~G7+Vd>s(Dv_fpi2NiiGlB*c!Ja?<+PDrPfxm zq9X87{XOtG7<#%T<}+ogLVDLv-fatGWA-?!hf0p83a5_HkYcEg+F2gbE`7ZMN?r@Iymt z*}WZlIsXx8kgUT8I^2wM)19<$+MTX+!=6t)5k|)cyz(+InT%cjQ-HHHurrfZ+@$)J ziQYY1({hEZD(y=~|4@?EAXaU@W;&~0K6Uwm1QnfW6tnM(Z`tOM;}(VX^EeNwY;A~X zVnPM^fU#@?Y=DcU$;LKlE|_*iWCBO5YkG5Aj=6-shw@f(MO;%^2?;_|PRBDTpk0^8 zRl2D9TKjNig9xsiYu*iPw0=`h?-sU!DlRUzc8%WFTs>72;|h;1XhJDq?)~nWJ+MIt z19;(eEc8I5TIaTcs}Lmt4^JgfiXZXgfnqlXqOplTn+;NYmvERPb2~d#jQ;eq*bD$8 zEDY!cO~plYwrcXY*l76cy!of+ic^7LiWyGr$3n9(0K|{KH#5Y^bhIG|X-FtsscShr zulnYN$VL5p=DkdqE)?B-vG)8_0Uqp}4d27+s?>U!N54Smf!se@RKN>vd2A&#O_LSW z*>86ehJqY~@L8!JVpgHFgW5>%5=wsK_vGnkZIpmabG)oALyH+YXt$37ZWyXVIWoHx zIwHQ=Ur?D)wK=8-8fNo$Wi<9ujh(~9R(6{nM=a&5 zN!A?2OeOH-?IfGFxb|N)iu#b2*Be1#5Nj+M5pKX_5M^pG?GVbuSk6sMWabetq?_@@ zX8D4MC;;!0MuhD2(wHb%Mf2lr^T@e_sWR7Xy=Hut1%A|sR&O&hh%7w!-gN(l{ zB^9ak_9>Kvp7r@4_TaW!ElG|fdW+p96(1{~EV6XcA(bc-3~#yroj960m=yVxzKJnt zTy~V#(w2csit@lAL}w)+!T7nMpAw4*sxCB!$X*@ipRmx-vA|UG^j18Yvs6S*2R4y` zU#cp4(5HS|3CML#lAoh82>&__=!(eipXPvQs?q9}pqzqv?1N@|;1fr&D#?C}x|d=+ z>0CT4#|gBV$xcBsF6mVFw_6^N_~;Qb68uY9Vr*XaB6u|QYRHGE+?sI?9Qndkdj?a* z;e`glB0S5>-;~c>;Br*`t8HpJy*LM-!-i#-F@h6~<#+mS4%HNjIo>I89p`Fp=uJ8m zy4SVxO$@>n^m8FNhu(i)yI6)e^K`S3*zu`h2!wwn;)Z5^`Q1WxD2Tb0JfJ56`y@mp z|6oz6knZ6woF$|9Ds-m0pWAhlQIbi2;KRF*JbsYN*2}_e_iT}Sn6F?|q-WN-ErWaH z+>=NE1*e>}M@#D>aYBJ`F$SYuq6(PzY0TgdzY3Lu18z zD*Vg>VJ(xaFR~bM9hU5zGa6DuOckV`*@{zRI76D+Y zL=vrrMIgkiKWyd0&7+m;44H^Vq`1?)ZHi@EtY;^;&t|6weS90_l1Fv8<=!}uC)mTK zxI`u4Eu{LZ_ccImX%}D&Imv7Icl98)fxFN525TEh!Z{ApelCL0#DutW(Ogj3JkF!; z_LPTZ@*!4C6zomW3eQ>JX?DUEq$NH7d4nElk87Hc;;I~O^3b!QY_y&^ISg7VGcI^a zNnW5n9j7p%ujW(6=zZN^I}qQ299b~3YcL%3B?M2^|B-UeS@pyD&gqe{s@`KHW|Hweq1jd!pF|78~Al(0p%*v6Dnm#R+i+Ide z_i|u`gRk-`I+U}_pB%ZPg^_;x3t~aCs}fx#N)|MJDzsHo-mCj2T93ABJK3fCkw%}x z!dgf{3Sphr^Do>Q?$u5IN&5zBf#Z%*q-EP8 zbo-DYpyz0|dHT2zF4bP@d7#}XvgwU~Dh2bCJK@y>W3p7!ROHUnt6|~niU)6&)0X?5 zy3Zw|27B5OC+yOg4`Oc-vLI#orX8UL1=)+|*X`y?5EJho(Ui)W#lbt&yw?+#LN$U@ zQ8ONsnx&%$6;jh}jpK*Yd@u#JW6_5IC2A|R)L|UMsVT)g2ww`-thvFro)rJL^QV>9 zaEr8+{uY+Q`y$RRf{^?G>1^92o`&;UB-LJ$>eJ2Nl(DI$^y}k)!sgNc66JH`XqLgM z?{CuP+Jf50V#Op;>!THx{?#j;Hy}#REg`Fy?L@$CG?1 zeam4I5-Mr?AnO%M6+rj}Ig&A_CH@4xMeJOb3xBQ_6`e75*}&@2v9Dpyy+IY-vQ+*y zbp%(J@|cPM0Ju1dJc{3F!L0(>xmt-^i?_@~Y`)ZHw-&|sWi6a9S3d^59ym%xQwK-e zE827snPTpAgU3P5+tPE~gi_;&J?CV_5*h8X@}06``V?zvB*NFWg%6Z-+^U1;Sqy$% z|KiHcz6Wo0ec72yeXc40vmU6Vl(R+Y`Nc38ZNeV8)x%oN<|=Pma+dzN)>n5$)e{+( z!9sD$pm)BU9mH3;^)5aUvd=&A*E~By83z9IEFqeZr+gLZ^?3`iLSStKB+J#Y?Zduc)nTPqIc~->UuOs6LYn`+x1Z1mR8JqD*7j zK7Iwii5IhV{cI=XPk_+R!yEI>Ay1N5fov2uyJNi855lm&)&qr6oj+h1y9blFXIIAR z(PKadsf`)|(ehE`bSKCkxBPQ5dWtZ6AU^L&lFacdgyd+~r%*u(=TW9_dts)XUzgXKosqw35ZfF}PP^A#2r*u>>zCzaM*5j4VuAFi!c*!mt-tNqux zqlIzzJv70sl;7qcMnByQjm?&Rs?JFYFNL3UR?uuJi+&5bG4(0Unf1-&a~~z&3QyM) zC;6~lQH@34qWGP%@;oKrq6`{pPtFgkAKDp|hWe|haGhqt$(?nr9-?A2 zNU-3d{%7t3qi>X&DBhlqT&;nM*SBHvMi(WD&==NXB6XKBnpY#PV~N$#7SpaoF;27I zz`?Ry-`ZZfO2;{OvSmw(-kGy_NGC1Hd4?d@iY#hG7YBI9e*am}Fb$CXhjQY5T9Pn$ zlSh${*qvcm*aZ^Xx#qwB#A1uGZ4V-+lHm|oeP%Thq@`+DGoljQ6cz1@dRL|_ZR35U zx}@Zb7|G0jpJlTN;fvbRG9d&8@i9!o?g=5;S3Fv=obcP>aJo$TKZ*bIfuJAm6OZ7dsnB}qa$D0^g=f}~IxrqN9wB@U(X8yo zSd-^a({xRQHst0PMI~w%g0a#mEtP`YK5TbSnkn%|-=gxSI8#&lIa4yKeV1^zeMlg~VcJwTpzHwp0i=fr$|mL{0MMOUO~vCFUU0XwyswYWz z6B=i%TU$_-eX%gXMu#}Me1NTF_qJ9>1o!9p$g4ljqmd;%PiWEMpW>`4e=ZS=#>6t| zIzv~>aT4)%>>DyK8F?YW_t59^WJB>Xtr%nb4IGzdjhc@`aq?%ePqu!Q+bkH}+CV%f zv{N5?ehQy4#U9-?^PrP`NmIc0c7EiL{sfZ@RHF8d$S^kdg+i`|l@R17X{;Qi9XP*p zV2C2d0n5Z!MycOVff?cy=hHq*hU0YRQRl@w{|-i2Re@f}V;-ze_ksNNPd5>7eB zq=&hUtFI2ny~aU)%oR2tuczVrB+=QKYX6nY{+8S3c;%%>t#o9p{DnbUe7sa%J*<*+ zS986d03=K3#K=@%#CP9EL3)0QwXBlah;R;E1WOUKAy4OskxjnqrAWijxWp>+;+4E!@ny88f z!50C5bz%Z8b0SD!46cBo^~h*%Lx7(oW_*l)#U9OilvbG;Zb^A20u2qmu_^2*)LXd$G;8 zQ8S0gV$3gl{ce4gbpEmF;>sW2MZ9$hqKG?jPq-DU2e|pS^#2W>p%k_Ku`f-{}jl-0sz4UK>Vi$0AxY%{y(h>Lj7MJPyis@3IP6Jo}d5P|3La* a{TKaTEodI-e>=eC^T7UF13v!4`o92O6C;lR literal 0 HcmV?d00001 diff --git a/assets/js/0480b142.50f49949.js b/assets/js/0480b142.50f49949.js deleted file mode 100644 index 575e7285c..000000000 --- a/assets/js/0480b142.50f49949.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[836],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(n),f=a,h=d["".concat(l,".").concat(f)]||d[f]||u[f]||o;return n?r.createElement(h,i(i({ref:t},p),{},{components:n})):r.createElement(h,i({ref:t},p))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=d;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,i[1]=s;for(var c=2;c{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var r=n(7462),a=(n(7294),n(3905));const o={sidebar_position:16},i="FAQ",s={unversionedId:"faq",id:"faq",title:"FAQ",description:"Smart contract call failure",source:"@site/docs/faq.md",sourceDirName:".",slug:"/faq",permalink:"/faq",draft:!1,tags:[],version:"current",sidebarPosition:16,frontMatter:{sidebar_position:16},sidebar:"tutorialSidebar",previous:{title:"Tutorial 7: Escrow",permalink:"/tutorials/escrow"},next:{title:"README",permalink:"/reference/"}},l={},c=[{value:"Smart contract call failure",id:"smart-contract-call-failure",level:2},{value:"Broadcast double-spending transactions",id:"broadcast-double-spending-transactions",level:2},{value:"1) for developers",id:"1-for-developers",level:3},{value:"2) for dApp users",id:"2-for-dapp-users",level:3},{value:"Input string too short",id:"input-string-too-short",level:2},{value:"No sufficient utxos",id:"no-sufficient-utxos",level:2}],p={toc:c};function u(e){let{components:t,...o}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,o,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"faq"},"FAQ"),(0,a.kt)("h2",{id:"smart-contract-call-failure"},"Smart contract call failure"),(0,a.kt)("p",null,"If you receive a ",(0,a.kt)("inlineCode",{parentName:"p"},"mandatory-script-verify-flag-failed")," error when broadcasting a transaction, it means that one or more inputs calling a contract fails."),(0,a.kt)("p",null,"There are several possibilities for the failure."),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Script evaluated without error but finished with a false/empty top stack element")," is the most common one. It means one of ",(0,a.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#assert"},"assert")," fails."),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(3192).Z,width:"1742",height:"132"})),(0,a.kt)("p",null,"Another common error is ",(0,a.kt)("inlineCode",{parentName:"p"},"Signature must be zero for failed CHECK(MULTI)SIG operation"),", which means the signature is invalid in ",(0,a.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#checksig"},"checkSig")," or ",(0,a.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#checkmultisig"},"checkMultiSig"),"."),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(4767).Z,width:"1730",height:"138"})),(0,a.kt)("p",null,"You need to ",(0,a.kt)("a",{parentName:"p",href:"/how-to-debug-a-contract"},"debug the contract"),"."),(0,a.kt)("h2",{id:"broadcast-double-spending-transactions"},"Broadcast double-spending transactions"),(0,a.kt)("p",null,"You could get two different errors when broadcasting a double-spending transaction, depending on the status of the transaction you're trying to double-spend."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"If the transaction you're trying to double-spend is still unconfirmed and in the mempool, the error would be ",(0,a.kt)("inlineCode",{parentName:"li"},"txn-mempool-conflict"),".")),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(3498).Z,width:"1170",height:"120"})),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"If the transaction is already mined into a block and confirmed, the error would be ",(0,a.kt)("inlineCode",{parentName:"li"},"Missing inputs"),".")),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(9165).Z,width:"1020",height:"116"})),(0,a.kt)("h3",{id:"1-for-developers"},"1) for developers"),(0,a.kt)("p",null,"If you encounter these errors when running code, e.g., testing on testnet, it is likely because the ",(0,a.kt)("a",{parentName:"p",href:"/how-to-deploy-and-call-a-contract/#provider"},"provider")," you are using fails to update your UTXO in time and return UTXOs that have already been spent when you request. Using these UTXOs that have been spent to build transactions will result in a double-spending. This situation is transitory and is caused by the provider not updating UTXO set timely due to, e.g., the provider's server overloading due to heavy blockchain traffic."),(0,a.kt)("p",null,"To fix this issue, you generally only need to wait a few seconds and retry. If it still persists, you can also increase the time interal between sending consecutive transactions, for example, ",(0,a.kt)("inlineCode",{parentName:"p"},"sleep")," for some time after sending transactions before requesting the UTXO again, so that the provider has enough time to update the UTXO set:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-ts"},"// ... contract call #1\n\nawait sleep(2000) // Sleep for 2 seconds\n\n// ... contract call #2\n")),(0,a.kt)("h3",{id:"2-for-dapp-users"},"2) for dApp users"),(0,a.kt)("p",null,"If you encounter these errors when ",(0,a.kt)("a",{parentName:"p",href:"/how-to-integrate-a-frontend/"},"using a dApp"),", it is likely because the state of dApp's contract has been changed by another user, who is interacting with the dApp at the same time. You are interacting with the contract instance that is stale, resulting in a double-spending."),(0,a.kt)("p",null,"To fix this issue, you usually only have to wait a few seconds, your local dApp will automatically obtain the latest contract state if it has ",(0,a.kt)("a",{parentName:"p",href:"/advanced/how-to-integrate-scrypt-service#listen-to-events"},"subscribed to contract events"),"; otherwise you have to manually refresh the browser and try again."),(0,a.kt)("h2",{id:"input-string-too-short"},"Input string too short"),(0,a.kt)("p",null,"If you do not set the ",(0,a.kt)("inlineCode",{parentName:"p"},"PRIVATE_KEY")," environment variable in ",(0,a.kt)("inlineCode",{parentName:"p"},".env")," file before deploying a contract, you would get an ",(0,a.kt)("inlineCode",{parentName:"p"},"Input string too short")," error."),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(8909).Z,width:"1978",height:"560"})),(0,a.kt)("p",null,"Please follow ",(0,a.kt)("a",{parentName:"p",href:"/how-to-deploy-and-call-a-contract/faucet"},"this guide")," to generate a new private key or export the private key from your Sensilet wallet, then fund the private key's address with our ",(0,a.kt)("a",{parentName:"p",href:"https://scrypt.io/faucet/"},"faucet"),"."),(0,a.kt)("h2",{id:"no-sufficient-utxos"},"No sufficient utxos"),(0,a.kt)("p",null,"If you don't fund your private key's address before deploying a contract, you would get a ",(0,a.kt)("inlineCode",{parentName:"p"},"No sufficient utxos")," error."),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(3249).Z,width:"2042",height:"581"})),(0,a.kt)("p",null,"Please fund your address with our ",(0,a.kt)("a",{parentName:"p",href:"https://scrypt.io/faucet/"},"faucet")," first."))}u.isMDXComponent=!0},4767:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/checksig-failed-7c97f34e3a1aa956bfbcc8251b0cf96d.png"},3249:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/insufficient-balance-abd131922a236aeb2935376131a7e077.png"},3192:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/mandatory-script-verify-flag-failed-0882ec42a75fb4fe3ba99bfb6ce4b338.png"},9165:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/missing-inputs-1febf7888158afd54aa92fe2a4a01bf1.png"},8909:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/no-private-key-12f4c8462221021714a767e397139d5d.png"},3498:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/txn-mempool-conflict-6de17c4edce004ecf236d56eba0bfead.png"}}]); \ No newline at end of file diff --git a/assets/js/0480b142.fc53a885.js b/assets/js/0480b142.fc53a885.js new file mode 100644 index 000000000..234eb9af0 --- /dev/null +++ b/assets/js/0480b142.fc53a885.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[836],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(n),f=a,h=d["".concat(l,".").concat(f)]||d[f]||u[f]||o;return n?r.createElement(h,i(i({ref:t},p),{},{components:n})):r.createElement(h,i({ref:t},p))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=d;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,i[1]=s;for(var c=2;c{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var r=n(7462),a=(n(7294),n(3905));const o={sidebar_position:16},i="FAQ",s={unversionedId:"faq",id:"faq",title:"FAQ",description:"Smart contract call failure",source:"@site/docs/faq.md",sourceDirName:".",slug:"/faq",permalink:"/faq",draft:!1,tags:[],version:"current",sidebarPosition:16,frontMatter:{sidebar_position:16},sidebar:"tutorialSidebar",previous:{title:"Tutorial 9: Ordinal Auction",permalink:"/tutorials/ordinal-auction"},next:{title:"README",permalink:"/reference/"}},l={},c=[{value:"Smart contract call failure",id:"smart-contract-call-failure",level:2},{value:"Broadcast double-spending transactions",id:"broadcast-double-spending-transactions",level:2},{value:"1) for developers",id:"1-for-developers",level:3},{value:"2) for dApp users",id:"2-for-dapp-users",level:3},{value:"Input string too short",id:"input-string-too-short",level:2},{value:"No sufficient utxos",id:"no-sufficient-utxos",level:2}],p={toc:c};function u(e){let{components:t,...o}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,o,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"faq"},"FAQ"),(0,a.kt)("h2",{id:"smart-contract-call-failure"},"Smart contract call failure"),(0,a.kt)("p",null,"If you receive a ",(0,a.kt)("inlineCode",{parentName:"p"},"mandatory-script-verify-flag-failed")," error when broadcasting a transaction, it means that one or more inputs calling a contract fails."),(0,a.kt)("p",null,"There are several possibilities for the failure."),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Script evaluated without error but finished with a false/empty top stack element")," is the most common one. It means one of ",(0,a.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#assert"},"assert")," fails."),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(3192).Z,width:"1742",height:"132"})),(0,a.kt)("p",null,"Another common error is ",(0,a.kt)("inlineCode",{parentName:"p"},"Signature must be zero for failed CHECK(MULTI)SIG operation"),", which means the signature is invalid in ",(0,a.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#checksig"},"checkSig")," or ",(0,a.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#checkmultisig"},"checkMultiSig"),"."),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(4767).Z,width:"1730",height:"138"})),(0,a.kt)("p",null,"You need to ",(0,a.kt)("a",{parentName:"p",href:"/how-to-debug-a-contract"},"debug the contract"),"."),(0,a.kt)("h2",{id:"broadcast-double-spending-transactions"},"Broadcast double-spending transactions"),(0,a.kt)("p",null,"You could get two different errors when broadcasting a double-spending transaction, depending on the status of the transaction you're trying to double-spend."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"If the transaction you're trying to double-spend is still unconfirmed and in the mempool, the error would be ",(0,a.kt)("inlineCode",{parentName:"li"},"txn-mempool-conflict"),".")),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(3498).Z,width:"1170",height:"120"})),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"If the transaction is already mined into a block and confirmed, the error would be ",(0,a.kt)("inlineCode",{parentName:"li"},"Missing inputs"),".")),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(9165).Z,width:"1020",height:"116"})),(0,a.kt)("h3",{id:"1-for-developers"},"1) for developers"),(0,a.kt)("p",null,"If you encounter these errors when running code, e.g., testing on testnet, it is likely because the ",(0,a.kt)("a",{parentName:"p",href:"/how-to-deploy-and-call-a-contract/#provider"},"provider")," you are using fails to update your UTXO in time and return UTXOs that have already been spent when you request. Using these UTXOs that have been spent to build transactions will result in a double-spending. This situation is transitory and is caused by the provider not updating UTXO set timely due to, e.g., the provider's server overloading due to heavy blockchain traffic."),(0,a.kt)("p",null,"To fix this issue, you generally only need to wait a few seconds and retry. If it still persists, you can also increase the time interal between sending consecutive transactions, for example, ",(0,a.kt)("inlineCode",{parentName:"p"},"sleep")," for some time after sending transactions before requesting the UTXO again, so that the provider has enough time to update the UTXO set:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-ts"},"// ... contract call #1\n\nawait sleep(2000) // Sleep for 2 seconds\n\n// ... contract call #2\n")),(0,a.kt)("h3",{id:"2-for-dapp-users"},"2) for dApp users"),(0,a.kt)("p",null,"If you encounter these errors when ",(0,a.kt)("a",{parentName:"p",href:"/how-to-integrate-a-frontend/"},"using a dApp"),", it is likely because the state of dApp's contract has been changed by another user, who is interacting with the dApp at the same time. You are interacting with the contract instance that is stale, resulting in a double-spending."),(0,a.kt)("p",null,"To fix this issue, you usually only have to wait a few seconds, your local dApp will automatically obtain the latest contract state if it has ",(0,a.kt)("a",{parentName:"p",href:"/advanced/how-to-integrate-scrypt-service#listen-to-events"},"subscribed to contract events"),"; otherwise you have to manually refresh the browser and try again."),(0,a.kt)("h2",{id:"input-string-too-short"},"Input string too short"),(0,a.kt)("p",null,"If you do not set the ",(0,a.kt)("inlineCode",{parentName:"p"},"PRIVATE_KEY")," environment variable in ",(0,a.kt)("inlineCode",{parentName:"p"},".env")," file before deploying a contract, you would get an ",(0,a.kt)("inlineCode",{parentName:"p"},"Input string too short")," error."),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(8909).Z,width:"1978",height:"560"})),(0,a.kt)("p",null,"Please follow ",(0,a.kt)("a",{parentName:"p",href:"/how-to-deploy-and-call-a-contract/faucet"},"this guide")," to generate a new private key or export the private key from your Sensilet wallet, then fund the private key's address with our ",(0,a.kt)("a",{parentName:"p",href:"https://scrypt.io/faucet/"},"faucet"),"."),(0,a.kt)("h2",{id:"no-sufficient-utxos"},"No sufficient utxos"),(0,a.kt)("p",null,"If you don't fund your private key's address before deploying a contract, you would get a ",(0,a.kt)("inlineCode",{parentName:"p"},"No sufficient utxos")," error."),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(3249).Z,width:"2042",height:"581"})),(0,a.kt)("p",null,"Please fund your address with our ",(0,a.kt)("a",{parentName:"p",href:"https://scrypt.io/faucet/"},"faucet")," first."))}u.isMDXComponent=!0},4767:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/checksig-failed-7c97f34e3a1aa956bfbcc8251b0cf96d.png"},3249:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/insufficient-balance-abd131922a236aeb2935376131a7e077.png"},3192:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/mandatory-script-verify-flag-failed-0882ec42a75fb4fe3ba99bfb6ce4b338.png"},9165:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/missing-inputs-1febf7888158afd54aa92fe2a4a01bf1.png"},8909:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/no-private-key-12f4c8462221021714a767e397139d5d.png"},3498:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/txn-mempool-conflict-6de17c4edce004ecf236d56eba0bfead.png"}}]); \ No newline at end of file diff --git a/assets/js/558c5b2f.b771f7f8.js b/assets/js/558c5b2f.b771f7f8.js new file mode 100644 index 000000000..9d59bb07e --- /dev/null +++ b/assets/js/558c5b2f.b771f7f8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[8199],{3905:(t,e,n)=>{n.d(e,{Zo:()=>c,kt:()=>p});var i=n(7294);function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function a(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function o(t){for(var e=1;e=0||(r[n]=t[n]);return r}(t,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(r[n]=t[n])}return r}var u=i.createContext({}),d=function(t){var e=i.useContext(u),n=e;return t&&(n="function"==typeof t?t(e):o(o({},e),t)),n},c=function(t){var e=d(t.components);return i.createElement(u.Provider,{value:e},t.children)},l={inlineCode:"code",wrapper:function(t){var e=t.children;return i.createElement(i.Fragment,{},e)}},h=i.forwardRef((function(t,e){var n=t.components,r=t.mdxType,a=t.originalType,u=t.parentName,c=s(t,["components","mdxType","originalType","parentName"]),h=d(n),p=r,A=h["".concat(u,".").concat(p)]||h[p]||l[p]||a;return n?i.createElement(A,o(o({ref:e},c),{},{components:n})):i.createElement(A,o({ref:e},c))}));function p(t,e){var n=arguments,r=e&&e.mdxType;if("string"==typeof t||r){var a=n.length,o=new Array(a);o[0]=h;var s={};for(var u in e)hasOwnProperty.call(e,u)&&(s[u]=e[u]);s.originalType=t,s.mdxType="string"==typeof t?t:r,o[1]=s;for(var d=2;d{n.r(e),n.d(e,{assets:()=>u,contentTitle:()=>o,default:()=>l,frontMatter:()=>a,metadata:()=>s,toc:()=>d});var i=n(7462),r=(n(7294),n(3905));const a={sidebar_position:11},o="Tutorial 9: Ordinal Auction",s={unversionedId:"tutorials/ordinal-auction",id:"tutorials/ordinal-auction",title:"Tutorial 9: Ordinal Auction",description:"Overview",source:"@site/docs/tutorials/ordinal-auction.md",sourceDirName:"tutorials",slug:"/tutorials/ordinal-auction",permalink:"/tutorials/ordinal-auction",draft:!1,tags:[],version:"current",sidebarPosition:11,frontMatter:{sidebar_position:11},sidebar:"tutorialSidebar",previous:{title:"Tutorial 7: Escrow",permalink:"/tutorials/escrow"},next:{title:"FAQ",permalink:"/faq"}},u={},d=[{value:"Overview",id:"overview",level:2},{value:"Contract Properties",id:"contract-properties",level:2},{value:"Constructor",id:"constructor",level:2},{value:"Public Methods",id:"public-methods",level:2},{value:"Bid",id:"bid",level:3},{value:"Close",id:"close",level:3},{value:"Customize tx builder for bid",id:"customize-tx-builder-for-bid",level:2}],c={toc:d};function l(t){let{components:e,...a}=t;return(0,r.kt)("wrapper",(0,i.Z)({},c,a,{components:e,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"tutorial-9-ordinal-auction"},"Tutorial 9: Ordinal Auction"),(0,r.kt)("h2",{id:"overview"},"Overview"),(0,r.kt)("p",null,"In this tutorial, we will go over how to build an ordinal-auction contract. It is open and transparent, where everyone can participate and the highest bidder wins and recieved the Ordinal when the bidding is over."),(0,r.kt)("p",null,"There are two ways to interact with the contract:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Bid: if a higher bid is found, the current highest bidder is updated, and the previous highest bidder is refunded."),(0,r.kt)("li",{parentName:"ol"},"Close: the auctioneer can close the auction after it expires and take the offer.")),(0,r.kt)("h2",{id:"contract-properties"},"Contract Properties"),(0,r.kt)("p",null,"According to the interactions above, this contract needs to store four (4) properties:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"The output of auctioned ordinal"),(0,r.kt)("li",{parentName:"ul"},"The auctioneer, who starts the auction"),(0,r.kt)("li",{parentName:"ul"},"The deadline for the auction"),(0,r.kt)("li",{parentName:"ul"},"The highest bidder until now")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"}," // Output of auctioned ordinal (txid + vout).\n @prop()\n readonly ordinalPrevout: ByteString\n\n // The bidder's public key.\n @prop(true)\n bidder: PubKey\n\n // The auctioneer's public key.\n @prop()\n readonly auctioneer: PubKey\n\n // Deadline of the auction. Can be block height or timestamp.\n @prop()\n readonly auctionDeadline: bigint\n")),(0,r.kt)("h2",{id:"constructor"},"Constructor"),(0,r.kt)("p",null,"Initialize all the ",(0,r.kt)("inlineCode",{parentName:"p"},"@prop")," properties in the constructor. Note that we don't need to pass a ",(0,r.kt)("inlineCode",{parentName:"p"},"bidder")," parameter, because the first bidder is the auctioneer."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"}," constructor(\n ordinalPrevout: ByteString,\n auctioneer: PubKey,\n auctionDeadline: bigint\n ) {\n super(...arguments)\n this.ordinalPrevout = ordinalPrevout\n this.bidder = auctioneer\n this.auctioneer = auctioneer\n this.auctionDeadline = auctionDeadline\n }\n")),(0,r.kt)("p",null,"When deploying the contract, the auctioneer locked the minimal bid into the contract, and at this time, the highest bidder would be himself."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"const instance = new OrdinalAuction(\n ordinalPrevout,\n publicKeyAuctioneer,\n auctionDeadline\n);\nconst deployTx = await instance.deploy(minBid);\n")),(0,r.kt)("h2",{id:"public-methods"},"Public Methods"),(0,r.kt)("h3",{id:"bid"},"Bid"),(0,r.kt)("p",null,"When there is a higher bid, the current highest bidder is updated and the previous highest bidder is refunded.\nWe can read the previous highest bid from the balance of the contract UTXO."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"const highestBid: bigint = this.ctx.utxo.value;\n")),(0,r.kt)("p",null,"Then it's easy to demand a higher bid."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'assert(\n bid > highestBid,\n "the auction bid is lower than the current highest bid"\n);\n')),(0,r.kt)("p",null,"The spending/redeeming tx has these outputs."),(0,r.kt)("p",null,(0,r.kt)("img",{parentName:"p",src:"https://lucid.app/publicSegments/view/bfe65136-2acd-4a46-ba63-a6ec4b6d7d4a/image.png",alt:null})),(0,r.kt)("p",null,"The above diagram shows two such bidding transactions, where Bob and then Charlies successfully bids.\nThey both have 3 inputs and 2 outputs."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"@method()\npublic bid(bidder: PubKey, bid: bigint) {\n const highestBid: bigint = this.ctx.utxo.value\n assert(\n bid > highestBid,\n 'the auction bid is lower than the current highest bid'\n )\n\n // Change the public key of the highest bidder.\n const highestBidder: PubKey = this.bidder\n this.bidder = bidder\n\n // Auction continues with a higher bidder.\n const auctionOutput: ByteString = this.buildStateOutput(bid)\n\n // Refund previous highest bidder.\n const refundOutput: ByteString = Utils.buildPublicKeyHashOutput(\n hash160(highestBidder),\n highestBid\n )\n let outputs: ByteString = auctionOutput + refundOutput\n\n // Add change output.\n outputs += this.buildChangeOutput()\n\n assert(\n hash256(outputs) == this.ctx.hashOutputs,\n 'hashOutputs check failed'\n )\n}\n")),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("em",{parentName:"strong"},"bid"))," method is pretty straightforward. It first checks if the bid is sufficiently large. If so,\nit updates the highest bidders. In the rest, it checks the new transaction\u2019s outputs.\nThe first output is just the next instance of the auction with updated state. The value locked in this output will be equal to the new bid.\nThe second output will pay back the last highest bidder with the amount they were bidding. Lastly it adds change output."),(0,r.kt)("h3",{id:"close"},"Close"),(0,r.kt)("p",null,"when the auction expires, the auctioneer can close it and take the offer.\nThe auctioneer must also transfers the ordinal to the highest bidder. This is where the contract controls."),(0,r.kt)("p",null,(0,r.kt)("img",{src:n(2290).Z,width:"1100",height:"251"})),(0,r.kt)("p",null,"The above diagram shows a close transaction on the right. It differs from a bidding transaction in inputs and outputs."),(0,r.kt)("p",null,"There is an additional input (first input) containing the ordinal we are auctioning off\nThere is an output (first output) transfering the ordinal to the winning bidder.\nThe contract is called in the second input, while the ordinal is referenced in the first. They are in separate UTXOs, yet the contract can control the transfer of the ordinal."),(0,r.kt)("p",null,"Method ",(0,r.kt)("inlineCode",{parentName:"p"},"public close(sig: Sig)")," is simple, we require:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"// Output of auctioned ordinal (txid + vout).\n@prop()\nreadonly ordnialPrevout: ByteString\n\n@method()\npublic close(sigAuctioneer: Sig) {\n // Check if using block height.\n assert(\n this.timeLock >= this.auctionDeadline,\n 'auction is not over yet'\n )\n\n // Check signature of the auctioneer.\n assert(\n this.checkSig(sigAuctioneer, this.auctioneer),\n 'signature check failed'\n )\n\n // Ensure the first input in spending the auctioned ordinal UTXO.\n assert(\n slice(this.prevouts, 0n, 36n) == this.ordnialPrevout,\n 'first input is not spending specified ordinal UTXO'\n )\n\n // Ensure the 1sat ordinal is being payed out to the winning bidder.\n let outputs = Utils.buildPublicKeyHashOutput(hash160(this.bidder), 1n)\n\n // Ensure the second output is paying the bid to the auctioneer.\n outputs += Utils.buildPublicKeyHashOutput(\n hash160(this.auctioneer),\n this.ctx.utxo.value\n )\n\n // Add change output.\n outputs += this.buildChangeOutput()\n\n // Check outputs.\n assert(hash256(outputs) == this.ctx.hashOutputs, 'hashOutputs mismatch')\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"It can only be called by the auctioneer. That is why we need to pass in the caller's signature.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'// Check signature of the auctioneer.\nassert(this.checkSig(sig, this.auctioneer), "signature check failed");\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Now the auction deadline has passed")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'assert(this.timeLock >= this.auctionDeadline, "auction is not over yet");\n')),(0,r.kt)("p",null,"The close method is slightly more involved. First, it checks that the call is made after the deadline using a typical ",(0,r.kt)("a",{parentName:"p",href:"https://docs.scrypt.io/tutorials/timeLock"},"time-lock")," pattern.\nIt then authenticates the auctioneer\u2019s signature, auctioneer is the only one allowed to close the auction."),(0,r.kt)("p",null,(0,r.kt)("img",{src:n(1817).Z,width:"720",height:"394"})),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://docs.scrypt.io/how-to-write-a-contract/scriptcontext/#prevouts"},"this.prevouts")," in ScriptContext contains all pointers to the UTXOs referenced in the inputs, called outpoints. An outpoint contains two parts:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"TXID: 32 bytes"),(0,r.kt)("li",{parentName:"ul"},"Output index: 4 bytes.")),(0,r.kt)("p",null,"A UTXO is in the output of a transaction uniquely identified by such an outpoint."),(0,r.kt)("p",null,"we extract the outpoint of the first input (first 36 bytes) and compare it against the actual ordinal\u2019s UTXO,\nhardcoded when the auction starts and the contract is deployed. This ensures the authenticity of the ordinal and it cannot be fabricated."),(0,r.kt)("p",null,"We then construct and confirm the outputs as before. The first output is a regular P2PKH transfer to the highest bidder.\nThe second output pays the auctioneer. Finally, we add change outputs if necessary."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("em",{parentName:"strong"},"Note the contract ensures the ordinal comes in the first input, so it ends up in the first output and gets transferred to the winner"))),(0,r.kt)("h2",{id:"customize-tx-builder-for-bid"},"Customize tx builder for ",(0,r.kt)("inlineCode",{parentName:"h2"},"bid")),(0,r.kt)("p",null,"Using ",(0,r.kt)("a",{parentName:"p",href:"/how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx#default-1"},"default tx builder")," cannot meet our demand when calling ",(0,r.kt)("inlineCode",{parentName:"p"},"bid"),", since the second output - the refund P2PKH output - is not a new contract instance."),(0,r.kt)("p",null,"In Function ",(0,r.kt)("inlineCode",{parentName:"p"},"static bidTxBuilder(current: Auction, options: MethodCallOptions, bidder: PubKey, bid: bigint): Promise"),", we add all three outputs as designed."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"}," static buildTxForBid(\n current: OrdinalAuction,\n options: MethodCallOptions,\n bidder: PubKey,\n bid: bigint\n ): Promise {\n const next = options.next as StatefulNext\n\n const unsignedTx: Transaction = new Transaction()\n // add contract input\n .addInput(current.buildContractInput())\n // build next instance output\n .addOutput(\n new Transaction.Output({\n script: next.instance.lockingScript,\n satoshis: Number(bid),\n })\n )\n // build refund output\n .addOutput(\n new Transaction.Output({\n script: Script.fromHex(\n Utils.buildPublicKeyHashScript(\n pubKey2Addr(current.bidder)\n )\n ),\n satoshis: current.balance,\n })\n )\n\n if (options.changeAddress) {\n // build change output\n unsignedTx.change(options.changeAddress)\n }\n")),(0,r.kt)("p",null,"Congratulations, you have completed the ",(0,r.kt)("inlineCode",{parentName:"p"},"Ordinal Auction")," contract! To learn more, you can refer to this example of ",(0,r.kt)("a",{parentName:"p",href:"https://xiaohuiliu.medium.com/integrate-ordinals-with-smart-contracts-on-bitcoin-part-2-d638b7ca3742"},"an NFT auction"),"."),(0,r.kt)("p",null,"The ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/sCrypt-Inc/boilerplate/blob/master/src/contracts/ordinalAuction.ts"},"final complete code")," is as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'import {\n assert,\n MethodCallOptions,\n ContractTransaction,\n ByteString,\n hash256,\n method,\n prop,\n PubKey,\n Sig,\n SmartContract,\n Utils,\n bsv,\n slice,\n StatefulNext,\n pubKey2Addr,\n} from "scrypt-ts";\n\nimport Transaction = bsv.Transaction;\nimport Script = bsv.Script;\n\nexport class OrdinalAuction extends SmartContract {\n // Output of auctioned ordinal (txid + vout).\n @prop()\n readonly ordinalPrevout: ByteString;\n\n // The bidder\'s public key.\n @prop(true)\n bidder: PubKey;\n\n // The auctioneer\'s public key.\n @prop()\n readonly auctioneer: PubKey;\n\n // Deadline of the auction. Can be block height or timestamp.\n @prop()\n readonly auctionDeadline: bigint;\n\n constructor(\n ordinalPrevout: ByteString,\n auctioneer: PubKey,\n auctionDeadline: bigint\n ) {\n super(...arguments);\n this.ordinalPrevout = ordinalPrevout;\n this.bidder = auctioneer;\n this.auctioneer = auctioneer;\n this.auctionDeadline = auctionDeadline;\n }\n\n // Call this public method to bid with a higher offer.\n @method()\n public bid(bidder: PubKey, bid: bigint) {\n const highestBid: bigint = this.ctx.utxo.value;\n assert(\n bid > highestBid,\n "the auction bid is lower than the current highest bid"\n );\n\n // Change the public key of the highest bidder.\n const highestBidder: PubKey = this.bidder;\n this.bidder = bidder;\n\n // Auction continues with a higher bidder.\n const auctionOutput: ByteString = this.buildStateOutput(bid);\n\n // Refund previous highest bidder.\n const refundOutput: ByteString = Utils.buildPublicKeyHashOutput(\n pubKey2Addr(highestBidder),\n highestBid\n );\n let outputs: ByteString = auctionOutput + refundOutput;\n\n // Add change output.\n outputs += this.buildChangeOutput();\n\n assert(\n hash256(outputs) == this.ctx.hashOutputs,\n "hashOutputs check failed"\n );\n }\n\n // Close the auction if deadline is reached.\n @method()\n public close(sigAuctioneer: Sig) {\n // Check deadline.\n assert(this.timeLock(this.auctionDeadline), "auction is not yet over");\n\n // Check signature of the auctioneer.\n assert(\n this.checkSig(sigAuctioneer, this.auctioneer),\n "signature check failed"\n );\n\n // Ensure the first input in spending the auctioned ordinal UTXO.\n assert(\n slice(this.prevouts, 0n, 36n) == this.ordinalPrevout,\n "first input is not spending specified ordinal UTXO"\n );\n\n // Ensure the ordinal is being payed out to the winning bidder.\n let outputs = Utils.buildPublicKeyHashOutput(pubKey2Addr(this.bidder), 1n);\n\n // Ensure the second output is paying the bid to the auctioneer.\n outputs += Utils.buildPublicKeyHashOutput(\n pubKey2Addr(this.auctioneer),\n this.ctx.utxo.value\n );\n\n // Add change output.\n outputs += this.buildChangeOutput();\n\n // Check outputs.\n assert(hash256(outputs) == this.ctx.hashOutputs, "hashOutputs mismatch");\n }\n\n // User defined transaction builder for calling function `bid`\n static buildTxForBid(\n current: OrdinalAuction,\n options: MethodCallOptions,\n bidder: PubKey,\n bid: bigint\n ): Promise {\n const next = options.next as StatefulNext;\n\n const unsignedTx: Transaction = new Transaction()\n // add contract input\n .addInput(current.buildContractInput())\n // build next instance output\n .addOutput(\n new Transaction.Output({\n script: next.instance.lockingScript,\n satoshis: Number(bid),\n })\n )\n // build refund output\n .addOutput(\n new Transaction.Output({\n script: Script.fromHex(\n Utils.buildPublicKeyHashScript(pubKey2Addr(current.bidder))\n ),\n satoshis: current.balance,\n })\n );\n\n if (options.changeAddress) {\n // build change output\n unsignedTx.change(options.changeAddress);\n }\n\n return Promise.resolve({\n tx: unsignedTx,\n atInputIndex: 0,\n nexts: [\n {\n instance: next.instance,\n atOutputIndex: 0,\n balance: next.balance,\n },\n ],\n });\n }\n}\n')))}l.isMDXComponent=!0},2290:(t,e,n)=>{n.d(e,{Z:()=>i});const i=n.p+"assets/images/close-f098212d4d8bfc7f2ae820ba5762125f.jpg"},1817:(t,e,n)=>{n.d(e,{Z:()=>i});const i="data:image/webp;base64,UklGRhAiAABXRUJQVlA4WAoAAAAIAAAAzwIAiQEAVlA4IDAhAADwxwCdASrQAooBPm02l0kkKSKkI3KZSSANiWdu+/Lw5d+R59ap4UCd/N88TOqr5b/leUpAf6Qv9v06PSl5kf0t/2/+Z96/0sf4/zgPWc9Sz9zvYA87v1df9t/3P2Z9pb1AP//7dPTb9b/7h2rf377ZfTP8P+OfrH5Ef3bnmxI/jf1x/Hf4X0E/0/5IeaPv+/nv617AX4v/Hv8D/SPIR2eOW/6v/feoF6WfKv9L/afyt9Cv919BPqR/XvuD+wD+IfzL/If1/95/7N8k/5T/deJ989/w/97+2D7AP4r/M/8B/Yf8T/2/7////tQ/e/+b/hP9X+5/tB/Nf7l/wP8N/pfkC/k/9G/239z/y/7YfMz/7/bp+2f/w9zr9Zv+3+f4sHHCNRDMT+iGYn9EMxP6H6lFa25QwPRCIZRfu4eF9Zf5jqSPRDDpqDcu9QX+Y6kj0QzE/ohmJ5kacTcJVqhPYi3UkeiGYn9EMxP6IYKV/hcaO8yFnujnBrctmSvGWiKw1YSb+hgXb8UBUGcTrBxvoVheMtEVhqwk4KT9J8i9Pdmp5AmgsXKT9J8i9PdnOTnBrctmStPN9EmtvivuAQbviZjxjLRP//////////////////+7DKCMkevFWiKw1YScFJ+k+RenuW8BrCsXMnscl6j23inEo4NblsyV4y0RWGrCTgpPfmqDtORSzJITqleIuRJ1SvEXIk6pXiLkSdUrxFyJOqV4i5EnVK8RciTqleIuRJ1SvEXIk6pXiLkSdUrwgiPyAfHdpKfo+C05eQl3NRdJM0jkJdzUXSTNI5CXc1F0dXmNT0UvirRFYasDinOvOZJSG4MfXuW5bMleMrwy0sykuc38oqx55PZ3uxv/Ox6Tltzsra3mbh3DtTKpvE8x+0tzV+HkL96gTCygnQNpv3cPC+sv8xxWTD/kgU/wrkeGYn9D0JLz0jSItkAlKkQgB7DALaNRwzsEkMraAvy3fKXisDAzC44+vJCT1tfEIyYYqDq2eiHIFTo6e0BZ8AlfYHbnYCBCLkbsAK/QV+7enpHMaNRD4HYNUsGqWDVLBqSq2XuogPi6Um/P0Q/u80BwObQx0/3KvVGgyyHt2MEOnlXqjQZUbPLS0T40GWPhews/hffFSUJjv/D50RkC94duAGxs3KV9w6cy+4ukF7cUQosygVQgTeL7LO/Z4lwRslWbcooRjqDE+omrYYoZm1zQ3Sgb1zJ5JfDIBsuSvw8R0EZR03wLe292IDwzZdgtDuxgBUqPxBIp8pyinBBjY7gNtV02K2S9gcH6ewtkAo9EEc5JrX4PzyaVrGEdNC0RRaDq1O2UtlJnkMWg6tYwdISD+NKHeEVuFMq0CdhbCFLGPpg/rL/MdSRsgoYVdXiPTo5wa3LZ/4KT9J8i9PdnN8lcduIeVXnDkp+L0Vl0PfYmYCGLoC2+f7Ov4D4EAc+uekC+rrPHXyX8Hpgr3uNWedlJB+um7yr48kCEI7ZEpWMq+5dv4iZGJrwN3h+UWD+1HRjB4Y/BsZFBBr9GKUYYlwYkLOd6zNXTYggJ7GNhhIEGN/rNWKs/kHL00rL4MYekvNRjXqOSWOXAvmgE9r+g6tYT+RuX7/pQbjeaRFssM0zhUHVqdjvM4j398iZ1mmcKg6sQomZxHwAD7mcR7++Tl22qPqLqSL092c3g9Vw2UtzV+Y6kjYWOAC+EUok4KT9J8j7gyV4y0RWGrCSkjv7ab9ZgtT4l8BK/9YHUMIqcIUFbCdcPB+Ht7MJ5Nr4TVjS4+xxzxRDohJ5WLvFpK3RiHHzTxud0NvhJasvi0J3Gnj8eSeqAFECEFO+Q99cYIuV9MgHi0KXUa9mrB+wTEbrr0/fo7aN4UsOMd7uHxT2YE+WzIHEUz0bsRpGOwqBdD18bd+LbiStZKMMJLaJDNpvVWXTD4OsvcH4LlrAFWwmf/FhIin6C8BkF3ObJqqyNeQsyoBFOO685ZGKRh1ZTvG9ve9JU4zDVXU4izvNyDFoOq/V02Kg6tYu9Ny/f9Gpz2/REWykzcllgtzfPkXp7s09QYi0HVrF3puX7/plXyZwqDqxCLrc5US4YtYsptSXXNQbpwu9KdqxaSPS4bWtRdl5D3w3l6o0GWPZLlzt0SOQl3NRdJM0jkJdy1XlO1YAA/vqztp4XEbkSMem4aiMV9aJ9RGqwAAARba4ov2F5yuh+uu0sR5732gcss9SJW2eSR4Uh0M6gfjFhsBPLL2xlC1kTDlU2Fz+0dYQT+YFN3eanj5cBBa4nfqDef79Qbz/fqDef79QcuOTItYfCkJQdUQAADgl4M2ldHOEtcdTe1xPJHvfkVtxuZGfH0CE2XeaII3vUTGVyvt2y53onne+Df+GJwDlQ6n1GizJRdtbediewpAAi15TWqbM9ZW+rpmVmjhQAGqBkka4Yb7ggwaJjXKfSUgAAAGlPJIBtglGzR/YiuD3/dW2+Tf+EvZVh2TfLxbVon1EOAAAWIAAYdyAyon68WJRS7HJ3vNHBKl6DmAgMc7JEHcVRZZVA0fGkZkdYHaeERlhUn7g56u7YN2GDF1PMO3uaLkI4xnYPKiLkFuLVe9GF81S0ICE0Pn0FwvgfIbWs5ASG1IXMHIf0+nE55UGFtGE0FQUNy6q+8hb8+efhgzrTQP15Ykds+Pi2DYl9Ux8kfHxbBsS+qY+SPj4tgrxcO+vfoGF8YKQofiafODeL2xMg3kN1GofyHQmAebHMIdJ5NmWywu/HhHbAlhd+PCO008pPj6/RqHXQWomJZSZiRsn7UfUDdXAwQpx0BOIkhWedHPu5GYpGcIZ83VNSOfss4OAVGWPVxntQrEI1zqU1KXVy5qH3hPGBu6oOSTTdN+Br8sCN1A2UxWYiD1Koa7PSKipP2l6phcSamMy69xEv/azuXIgPl6F/4SSoRCQx9QuFELbYAAABLQ2mCjxFOrhObT7H+7n53u2ulE2BIAex3+5iLsLp8lhNxhKkHI0iNZ9tYFLJtbGb2r6v66kwK4fP5yvGxqfCZEBzujD/3RAYv2YbX/TO2IZ9/vhEP4h4jW5vq+6XFyLSE63U7GyB/izM7jYrNoOQZR6pZ+IJbgSqqi+Kxv3iUStsKOEandSmIF9bUMY+LKTW2d0mLlFXBigUtq6cXFVDDfQhmLGhwNztZvX8EB25kCG5khoFkLze8AAAIf/4EhFUKkq3oNhF3Mn056qUX29y2U96LAAAAAAA88cXqOrjzoTWLKNF15RLmPItL6B5Jv+ZgW9w+QK4V+7qNZXfsDrUwQoIblvgCTuNwZs0ILRVdElT7G13vQ2HtFwodXgDo9Bs/HnckbKNpbiO9NiAC6WwnCDnkXkvAvJmKIA0RsrXpezSBK9pJTWBMKkGxkip1SL8a62k4Xb+f960q7Ds0T0gXjCRb2V6keMWhlxyBS+BHtNJwlC/YK5CZeOF8wOwnOvPE58POvgqo1reMI/k+3R1aD6WyinZ/jr5ISSYZnDi6H1JdUHVvnFPgH6p9Ip0DqS/38gEDClsPONpvA6uQghqXaGygjt2ukDPZPnzOxE3sg0Kkw1Z1jxBRisNv92YbUXStI7o5oSwpJWFWv6C4A5Molwxk+y95FIKkGvK/sH5tud2C4IpNbxXF9Mrmvfp0D/9unxK7ycYA8CIyPRFfsiKX2vyU88zlIWhsNoYU6d7TDYoj3QBpWXxqwg+nmmjR5485DD6+guwvpEwOgF/wWe3YLtyhFJUISFjNYaKiH7KsLH/cfvzx8Xn3fZVR6MuT3BdOFxvdNh2Pixwd6i3mW6l5G90phTFGbKMPGWf5rrcsU91OP62+cjfL9T0pazv+aV6KDsyEsdZlJJVIp/KOYHnQhJkq6BMQfLb6ZaPytbnv7IWMuEoAtaTF1DAWcLG71gQfzMQvHUzYArAGH2p9zf5jbjzfuLisqZBAP2MLRABBIhMmpgB8GoAHO3vNJJuLP0bK9AGsCzbOJenabqoAeUZcHjlAACcBhyrn2KowzeLvZejCs2C04N9s12vAWMXkYDrszKsEK9/stVjgOALNdNQKiqtanIMVVfq3PnSLeWEduC5C6ITktJlPb2ek4UUihMf6y65Hn7jbJBtLoAEoFAIs+3EeAoA5TTa8IRq1hbVvak2iYEro3jE0rnpHUJrMxtWJNwaqhOnN/cffBEDycWlJbdcqYG0Vt0dSc1GEPH/fT/ShPWyIw7xLxe3PUFAhHE461fxi+L5mofuLHRgh31WJVBkoQQ+/iuq925BNKExHXRQavD8l6YF3vg+FlFBYcZA6oRN6O4py5kYDyk0ac68yyxKCaQ4dFjkNTy3SHHdiP8PevU/koJGWONN29JNHeKl9JY9p2hGayAMZvo0qY4rtVp91/PgT0rEy9fjoxlQdWkQxQOOhJ9/zCFgKv/WKyGr5fG17WqefcmCPCoHpCkVR9P9wpThgoBE+HONEDIq/RmIdGfNw33NGM4Bri/kYCwtCwVn40T0g0G/FwXzbQ5sysDJ5dFJX0gf+YzvSxMoBTSCi28eQXQR2SiYIHVZEuGxaCMqdORche0ApGSvL5uBjJRst8sBT8PXftPYeOUjCrcShUBuNbRZVQM4KAK5LYUuTHyZ7jTfVxq5vU8UbOd8yxI/GutzZohYIGFujuYJO6vSyjk6nErPuF03v0OyOhRXyzquSQ+4UjUXGto+rV3snttWYmEH4k1ipvv5m7GecIM8quojzUiLZV8R8EbdlqACtqh0qEX27aSJgdJ+X3Xj5HzxgMjmsFoe8u6YvY9vzS6wk5UkmLkEYF2Ckt7d0HoTVfs2/iE2kqHXGcBp8xrPWYuoMzWqTDL0lgI7bplCobFzMwMSFzgHJas1AQUVHkt7jixKawiX5N+tlZEq3BpzG5TOv+2dRHyULmcrBfCUAlJNWedtIXeIKjRo73GdJlxiOYfsb9W3jBNxKeAHWuujrycIUrJO69+qdAr9qpSXa9cabNIiVfFC8tWIzkK6g/ASFWBOSS8VSAdmSYyiZC1MeA6uNm2n19cirZ0cJLBhqa0R8R48xYoGi20AHpRrj6yokP278Dc9bA9Hd2YCOv/H/9ZtfCGqrnWKaKbKO/TLH+sTrTb7yYI80rcNhzRtEnyuMzHkBgUyZLGfhMM5CcODISnll5mBMCuATlyfTYwZwBu0sFBLt/cekCtKn3Ncb7CMSwf/Vcivj/ld/aDF1we8AWvnp8/5urX/Zv//xYSyqYqL9JG7qUMv/461g3+xqaFZehN/B8Mq24OwI00xD+3r5TN+bkacalBqUX3RFvjLLV8NBpRykGraj+ldn30hCRzwaUvY9mv91/+MLrv8ndaMnHDz5gLnNOgAAyrwwFPqU/9EszWshYyvKTg6k15KUD4J0CH1P4XrlKevxJVmI2AfEQnxgIx7G2bogQbRIDKAZgQX+StR8E5f+H0TJGn9bkfnPViuAv9ZH/023Z+esA/vWpsx0vsbju6W6funxZ1soF+ffKqrA0SgVsSWj640/7ADe3JUDdFDMiwAHXJDk+nGunrjpfjHEXcWEfdrGd/qt7e1KierZkN2NJ/Fb8PkJlWmAvJNu4fcgDFXaJkCurZuOhZhXkoJIS5fmSKeXJUworNFV1BCdAnq+uuxIKswY2TXK31lUJ/e+l3RH5OoIuL6kJsPMkLHxSEhpeHyNyc6aq38vzLGOc/zA6HEoZX+gb8+gmziKlO+2HOctpHPJrsyCP19M5dX0+s6QhLFrQQ4INU1IDMQjG8pvH3rVq4EFFqB/ls5J57rhEx2JuDg7qkyjBsiUNhGluLeNCxxZ+gSDq4Wyej2lSTNOX3M+dD78KC7GEL7W84d1Q/DKLqZpn656nIqidLpFPEm0eLdw309hChVWok8JluS+As08wH68MS2G9d+4EYvhe5Y/Zb4GuWONBCAEPSeoHD/dX69sAYmC2HpsuMHAbX49BLzfRUe4T8mNNwvhH1oAD0DVq0HhXVDz5AqHHk9bptp9exS5W/ow986xPGl+UD4RlFNaDsAqQ9ljt+qrA3zFFqsC0Sr/ETdpQ0EV8CwSJgPNFfkKwTyPT/cuX/I592lbgXJidFMFOFeJz82t/j1619Hz6edN/kkJ9pm0nL8uMAWNX7wb5c0m6MFehU8NJu/GpWDI1niqMHJQlusNROEhi1aS7/otZM220lb+XIDBRGPlose7PcG0tlpkuBZhtm0M55sEflJslF/NuUu6ufWjsSwVeIw644UVJVWyY/p6wM8rB7GKVW9noOLlZmMI1w+WO8FRIq+wqewnZsMGwkaw5FwqK16WeyFy6yUub+kBXRZFde7OMGc8vxQXvfFXJllSkjJNwXvnnreK1UY/99c8nq8m6ABnCMrzE66Nh+/NCOnyFN8gKye9jyizwIWOIwuVHWIcxE1VBaz3xOU32Pl/HaZr7Eqmk4/0YRRb3MVlgTiE6HmHSDOJ+lBJHCtuz4JIP4cpPirbrwQ0wCXF9lZEhLYNTChZl4Cgi7lK4id9kmu10Rq/hXHis65Jfbj44rlZCJoAJicBSgvCJK4UdXD3ggBZIj5eb4xXqz/4iscGReCXnR+AseRN0xA341KXROIqCeQYbhVvnWHAiFII9lFESIfnU2uExhJtpfX5v47bsY0vKwf/16W7r7d8EdRuCIWdcor/wE8rN/WL1SLGkCvidwBVr7p6msr45C3m0cfM3XUU9iRJloS56DsR7tsi1rHA1iEqkFPnPTlkZ1h31x73/PyX1i6lnosj3gMNSFHdteoGT7uOwNRDJ/rERH8bq5ikiPw8UDsz6u6s4Fl9wzW6MBcOvKwavjZbT0zbzDQa9jlWtK/LIkAOAWM1nsFXO/yud+HTJf+G95GBswu8DPij0j1HfUGSE831/Sy6qcyqWR8mSoVB/xHasUrWqJA4Gbtm2W/cMEg4RsBSVpFkUwVLhuflpcLGbw4utgl+iULcJsskgC3ooi7A/kPwyLFN3F1DT5mqi7BKnf+02Nw9gNW8+Ave9hH1gwC4lBIzLfw6SSrrlofhvlvippyDxaqDLtqMc8EKvMuoVIBJKEzQBdmZcO93ybVTucRBQ2CQRAAQcgAAAPRNAAAiREDUEAAYV4AeSy75EUEQxT+OBcdoACQlRrmIGWx2SZRCv1/X9fqiKAIvGjNTmiDTb0GbISUowoq3xE5I+Pi2DYl9Ux8kfHxbBsTUZyAyN2O6LNZAmtTTYKvbYl8+Sxu/e8pneyahv7rC3TIiyKis3Vc/Zj5+/l/6qS4osZLfxzkNNrPHR2IstYQK6Ol2Y+GJldb1aii0Ixjd1Ivt1JEVSetjQMQeURDXQvDcW0bfAMzJ6lrjxnJj9b/oluP4gc0GcZ7SlE8l720MKOxyJltLZ//Yi7NPUzfaYxBnzHzqJ5NhyXJZLT01DHjMZhqvY3eR7Y4U872GHjVYa/SNPXOEgggPQ5pDs7e4L0LCAk1Ik04awMEakwIEjWuH5HccHyZQe34N/jf/Te2A8sJ4HYEPyA4pgNtz5LjJAhS/4o+MprYJesLhC2z2bbd/ACDOlWZrkCP9fLAfPHuxdoNo7R8nvssmG5XOU4UoAyOF+uzp2fSSBv+X72Uzc1a8+lbsCgv9S8PIFR1kHv3fGneoduTXW5s2LADC9dSmZ2tJzOOiwzOIAV7C/aCizf+vPbju9BY6nei8iElahS3HSmONW9is+tf9lVQAPySKpC8E1t0nm0YzHy06MCZQ/71Gt2u2FgtE3reG0cZrnaZvduGgLgUQFFyHPrC7mwou8Ax0p8KcrIM/4YRjgDyLZQJER92+xkG9Oz9xeYKXJmCANBebRyAqGzXj4SKH0QXgF+I6bVUGhGXgi24qdtfcX4wjz/R4U6ObewttLcjj4tD7f02Od6D/gml0Nkp6hA168YxyOUXp0CuQUOPyvtWlhj7yHHohDb+tt7cjtmGOGx8CXL/ow+qMX3Eu7xmsYqwM/gKcCIywz+fuHCe5nW801yDo7/8ssJ6yyI37Nt6VQDu1zsdPlzZf8Z1nzwGucAnXG2b8dS2S6qDP62oawaGMlUZ2TOWcMtriNUjzKD6uTKW9CfvZSvIfF+SniPT25gfXg6/Dbgx+FBFt+UGh4I9UkAJzPRVjEAVzyQAaY90soOHWT3UDe9xLnqGL7yupNGzqwSXAxs0a313fNVonpqfeehdFsBz6DTnu7DhcHVHRMg1hD1v4YQ13kX88ejz4wjzg1eyJNNMPZOgedBNrDdDWOC6PZpMqnrdKZuY9ok1b6bwyvM2l8Mh6M0eXFmFcIDuOLSpehPAA2JZ9e+yRsqIc5Mjyc2st8Ko+grK5miPeSly7E7rWkxipzSCppBN83F0plR7XNkQ35Shgy2saNy9WI7N73un+fGkhaJikJe2meTvMxoHo7/h/BwaGRnpmKvIJmouDkje2AsiZ0zEPelpkKeq8N8sq3bnyGkFWw71H7uSoTw8A9pW7IBfL2wsoqrit1QCu2NFXIZLXmcgANaYYUv6qbJZb2C2IpSs6EH04LUgEYCw8jLbYLUSPAWWQ0tY6mrjxdOe609dSJk+kiZe52zaNOtTrNtXdhA/M5/WXnruiUSIR3ht7UtVuh1FHIAiONQqeWPe2jOxDKePxcceT7xR/tBbp+KfGroicGmTth165ZmZ024VSTnuDV8QDGhrSDXjP6tyXZa65RHnGeFk1S3vicCarawWJBgMXQUnJlIBfg3x2P1mAyMKRr8v1vRcMdxASJE6+KdZAxamRixwRduIB7LMuYRBAGuxnoJ9Uo06yAAAACYmrZKHFLCYrRAA6dJBE5Bwbg6EPuG6FRzdzDOV3tj2+ACbAJNWsEAADJkBygAakKuAAAGLXksdgAAqK14ZUwzkh8O4OthlQ9Wl4MDLHBkEvSNk3tugAZ4oW5JLDylOVTlphLE9rpNUmqTVJqk1Soc0h/+5cuXLly5cuXLjKwAU9iaJ4ass1rPYtpTeUYty1eYwH6rUF0EHn7ONFsb9KeO7iPyZ2Y7dd94O2DQP7tdR6n0Bc172+Qflc9tV8d0+aqrOTJnrWw+3k97B+8sEpSAsAJAqXQBcE7SSWVYTptjHZROKSS2quxyTquux9Bv+bEZnBFY9ImmIPPofYOYzb16HgTT+b3bNm27RFqBTyuvJmd8knxHWMXKMAocDCewVw8uO9ehE99fvytFsDglUeMm4zYodjZbA/FnFIt0AlgiFEnUYYwAQKg1ymuRClIGXdPXdgsjTGuz6Ir3kjnCeDUlvIYM6j1HsBKV42TP677slrW3wH4eQWf0f1upWDzP6YaoJEUFkVBGigrn3KF6cgvAh9M7RPgy3cGhATOn7d4kFnZuFUtykU31e2LRUr2F+CcwM+EMhZ3geEUt4qY3CWUwan3Mni1TGtThHv4kwhx9EUFazpUf1irHT7G9/C1O1vXZxN6xPMYBMTWiGUEkJesJTeY0Q/896mb1rj+e5yBW3tRchzRclLqs+yg+dlQGwLckz6Ja2ojBV4KYzk6+Mu7GKAGDkPzYOq442KmxHcsjBsxJz9+E23x2e8n5lwCO97F5WQazmpDwOp6d9eEkMQRUp3YNE5+HSpK5qf8DwbymxT031XN+3Knqryu2G/+02Sa05/1tAHuWtSSkPR43DZe/WDKmcwfKTBNO3VDh0Rgfd+noyMmOZwxJXLqwqrdhBafZLuQpTpp373awKb7KFO5MI009fqnredkKz13tN/VF5m/DxCP3zU+L1evpEuvWDLMX7wJ+07siV7Vn9bIgs9kqtCvSLwPmA7QLn/D+xlPQcya3tlXroaPmgQjypsL1hcrId5NjZsZLnK4iTu+OxB/AOAd4Sfg+ZqsCBKmnc+cO8DQf+EcQ3mijrJAveEGQR0g1Dim4wRr96xU4IeR9Nbxd/WolNOWiq1lYsdp3Mkmdm3peaM7Us8aak/jMbP+ovKc7Y3EHjs5hD8eldpoX3EMq8LgShBsJ2h6j3RBkwHyj407gPpn5r13XRPDDQQmEGXEOgFbqcDgNfSTfLP3jJ63FrL2YYc6r+vtHnmIcjBHbtEMDOKnJanP/Xa31thz5F8lWSxfABsK44RDkHCHOp6WQSXWMURscAVTXRZTMlbinpFDNnauB7C0tJlc/YFdBomJoDJM19JFMYf5e0g10VHtxTxAkSNue7xxiQ69bao2gvMIvyhvzBejfNrDF40Q4JsweCL/+6RDmjNZO9ZLgrKuC7OgiSxrkN5NPcMb8MDqsf8oyVLoyL+buvo44v5cGqDX71ipxCIMoASTpysODyOLhydD+EsSpKMdfWBBEMcy2ReYcMwVGIjUL0mOBP9nFYHMrFaurY+c8VB4IfHssMQVtLrQIM0UKUCBp/VDNMo5HH84Vrn5O5rVDIT7bmW1EnQ4oYkDsWwqZ1zb+rCQpCy97ROLFg+k1jVhkN0KESBF1roznS+EJlmZ8+EZqoC+T7QYIv2nFa8S79CbhrPO5KKes1gDiZsW2M8tc+l5pP+uli7vtdmpBbdrISFPNu4I9GcrMxKQALgwTE5d0WcKo1YzCMzRt2c8m4wziaSIkgA8jlvSDZ0YM8VneKF84Rm2oy50tkLcChZ3O8hfUoEG28UBPv4dLxSgPeVYLewaVf/DZ19JbPddyS5ayxjSosuW/UoBnfhcfe4ljTdQr2OApMp4/GCn4nW09Aj6jRwRIG9XLnPxV57hmnUgQXH7FO32kfdIH55OZVlavMH/E0BHH9D6bEIJWX4Gzw5k0xi9BZiAEZatVebSDV+oqQ4TC9a5a+AltchaZGNReWFyBpsWLe0nI6Y6b3o6CO/0l0r4skSHXI0kBBGOXuWSEiRSoXCcRALFEfKumnzrZwzNr41SRZ9oELTn4ldrvu68E3VT3sD2IyxwC1384J/lsKlkvczg0Wyq/++zUumjU5P9ykMZEfO/H0IDFsew8GGXtXbP6GfW/OC9vxpJVACrS/0KsxnFkGfgXUq5ubziDH76tuzdpYtCXEzbC7ue4CcN5PVglsJxpXmChrsJMbeEtkMjxeBdckadbKCopaBNaewSS6gAARbZ4AG2rwxungZzngh8Gt7nG9Nnyrk+2agdhqRnh5soidYBGigncAAERbpAU3NHPbHWKB20BxU/uViTCApedLlqwlx/oJ6On8d96/sksr//zmI/6jWwYTY9L/Ur/+C7Ev7jNgxXLBZxqZu0cpB706+emX42be8kekTWq96VDZvmy5TDP//i2ow5qF8ryV5HI0u2dhe9n8c0i3EFVoIm6TfLsqNbqyqyP0x6WrKma1F71Hnf94oSXKHLK8MEKN5nXFsr3qPiNgvLnjA+qKoc3gRFHAv28Q3WOAifs9NA9WdIsH1ZHTM7wWQoQOXKDZyNetXad4oABFWElGugAAAEV4aWYAAElJKgAIAAAABgASAQMAAQAAAAEAAAAaAQUAAQAAAFYAAAAbAQUAAQAAAF4AAAAoAQMAAQAAAAIAAAATAgMAAQAAAAEAAABphwQAAQAAAGYAAAAAAAAASAAAAAEAAABIAAAAAQAAAAYAAJAHAAQAAAAwMjEwAZEHAAQAAAABAgMAAKAHAAQAAAAwMTAwAaADAAEAAAD//wAAAqAEAAEAAADQAgAAA6AEAAEAAACKAQAAAAAAAA=="}}]); \ No newline at end of file diff --git a/assets/js/6eaa7f88.25e5cc9b.js b/assets/js/6eaa7f88.25e5cc9b.js deleted file mode 100644 index 247bc84e5..000000000 --- a/assets/js/6eaa7f88.25e5cc9b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[7154],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>h});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=a.createContext({}),l=function(e){var t=a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},p=function(e){var t=l(e.components);return a.createElement(c.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=l(n),h=r,f=u["".concat(c,".").concat(h)]||u[h]||d[h]||o;return n?a.createElement(f,s(s({ref:t},p),{},{components:n})):a.createElement(f,s({ref:t},p))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,s=new Array(o);s[0]=u;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:r,s[1]=i;for(var l=2;l{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var a=n(7462),r=(n(7294),n(3905));const o={sidebar_position:10},s="How to Replay a Contract Instance to the Latest State",i={unversionedId:"advanced/how-to-replay-instance",id:"advanced/how-to-replay-instance",title:"How to Replay a Contract Instance to the Latest State",description:"Using sCrypt Service and sCrypt client, we can effortlessly create a contract instance reflecting the latest state as follows:",source:"@site/docs/advanced/how-to-replay-instance.md",sourceDirName:"advanced",slug:"/advanced/how-to-replay-instance",permalink:"/advanced/how-to-replay-instance",draft:!1,tags:[],version:"current",sidebarPosition:10,frontMatter:{sidebar_position:10},sidebar:"tutorialSidebar",previous:{title:"Time Lock",permalink:"/advanced/timeLock"},next:{title:"How to Build an Oracle Service",permalink:"/advanced/how-to-build-an-oracle-service"}},c={},l=[{value:"Step 1. Offchain Helper Functions",id:"step-1-offchain-helper-functions",level:2},{value:"Step 2. Create Instance from Deployment Tx",id:"step-2-create-instance-from-deployment-tx",level:2},{value:"Step 3. Replay Instance to Latest States",id:"step-3-replay-instance-to-latest-states",level:2}],p={toc:l};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"how-to-replay-a-contract-instance-to-the-latest-state"},"How to Replay a Contract Instance to the Latest State"),(0,r.kt)("p",null,"Using ",(0,r.kt)("a",{parentName:"p",href:"/advanced/how-to-integrate-scrypt-service"},"sCrypt Service")," and ",(0,r.kt)("a",{parentName:"p",href:"/advanced/how-to-integrate-scrypt-service#step-1-initialize-client"},"sCrypt client"),", we can effortlessly create a contract instance reflecting the latest state as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"const currentInstance = await Scrypt.contractApi.getLatestInstance(\n Counter,\n contractId\n)\n")),(0,r.kt)("p",null,"However, this method is ineffective for smart contracts with states of type ",(0,r.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#hashedmap"},"HashedMap")," or ",(0,r.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#hashedset"},"HashedSet"),". This is because each instance only contains hashed values, not the original ones."),(0,r.kt)("p",null,"In this section, we'll use ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/sCrypt-Inc/boilerplate/blob/master/src/contracts/crowdfundReplay.ts"},"contract CrowdfundReplay")," located at ",(0,r.kt)("inlineCode",{parentName:"p"},"src/contracts/crowdfundReplay.ts")," as a reference to explain how to replay these contract instances to their latest states."),(0,r.kt)("p",null,"This crowdfund contract features a HashedMap ",(0,r.kt)("inlineCode",{parentName:"p"},"donators")," that records the donors' public key and their respective donation satoshi amounts."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"export type Donators = HashedMap\n\nexport class CrowdfundReplay extends SmartContract {\n \n @prop(true)\n donators: Donators\n \n ...\n}\n")),(0,r.kt)("p",null,"This contract has three public methods:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"donate")," adds an entry to the HashedMap."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"refund")," removes a specific donator from the map."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"collect")," destroys the contract without updating any stateful properties.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"export type Donators = HashedMap\n\nexport class CrowdfundReplay extends SmartContract {\n ...\n\n @method()\n public donate(donator: PubKey, amount: bigint) {\n ...\n assert(!this.donators.has(donator), 'donator already exists')\n this.donators.set(donator, amount)\n ...\n }\n\n @method()\n public refund(donator: PubKey, amount: bigint, sig: Sig) {\n ...\n assert(this.donators.canGet(donator, amount), 'not donated before')\n assert(this.donators.delete(donator), 'failed to remove donator')\n ...\n }\n\n @method()\n public collect(sig: Sig) {\n ...\n }\n}\n")),(0,r.kt)("p",null,"To replay the contract instance to the latest states, follow these three steps:"),(0,r.kt)("h2",{id:"step-1-offchain-helper-functions"},"Step 1. Offchain Helper Functions"),(0,r.kt)("p",null,"Initially, add helper functions that update stateful properties in a manner ",(0,r.kt)("strong",{parentName:"p"},"identical")," to the public methods."),(0,r.kt)("p",null,"These functions are defined within the ",(0,r.kt)("inlineCode",{parentName:"p"},"offchainUpdates")," object:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"class CrowdfundReplay extends SmartContract {\n\n ...\n\n offchainUpdates: OffchainUpdates = {\n 'donate': (next: CrowdfundReplay, donator: PubKey, amount: bigint) => {\n next.donators.set(donator, amount)\n },\n 'refund': (next: CrowdfundReplay, donator: PubKey) => {\n next.donators.delete(donator)\n },\n }\n\n ...\n}\n")),(0,r.kt)("admonition",{type:"note"},(0,r.kt)("p",{parentName:"admonition"},"The object keys must match the public method names precisely.")),(0,r.kt)("p",null,"In our example, we only need two helper functions since the ",(0,r.kt)("inlineCode",{parentName:"p"},"collect")," method doesn't alter any stateful properties."),(0,r.kt)("h2",{id:"step-2-create-instance-from-deployment-tx"},"Step 2. Create Instance from Deployment Tx"),(0,r.kt)("p",null,"Retrieve the deployment transaction using the contract ID. Subsequently, ",(0,r.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#fromtx"},"recover")," the contract instance from it."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"// Recover instance from the deployment transaction\nconst tx = await provider.getTx(contractId.txId)\nconst instance = CrowdfundReplay.fromTx(\n tx,\n contractId.outputIndex,\n {\n donators: new HashedMap(),\n }\n)\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Note"),": For more details on the workings of the ",(0,r.kt)("inlineCode",{parentName:"p"},"fromTx()")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"getTransaction()")," functions, refer to the documentation ",(0,r.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#fromtx"},"here"),"."),(0,r.kt)("h2",{id:"step-3-replay-instance-to-latest-states"},"Step 3. Replay Instance to Latest States"),(0,r.kt)("p",null,"Invoke the ",(0,r.kt)("inlineCode",{parentName:"p"},"replayToLatest")," function to acquire the latest contract instance."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"import { replayToLatest } from 'scrypt-ts'\n\n...\n\nconst latestInstance = await replayToLatest(instance, contractId)\n\nif (latestInstance) {\n // The latest instance is now ready for use.\n ...\n}\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Note"),": If the ",(0,r.kt)("inlineCode",{parentName:"p"},"replayToLatest()")," function yields ",(0,r.kt)("inlineCode",{parentName:"p"},"null"),", it indicates that there have been no state changes for the contract instance. This scenario arises if the contract hasn't been interacted with since its deployment or if all state modifications have been reverted."),(0,r.kt)("hr",null))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/6eaa7f88.2f89a807.js b/assets/js/6eaa7f88.2f89a807.js new file mode 100644 index 000000000..30d264700 --- /dev/null +++ b/assets/js/6eaa7f88.2f89a807.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[7154],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>h});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=a.createContext({}),l=function(e){var t=a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},p=function(e){var t=l(e.components);return a.createElement(c.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=l(n),h=r,f=u["".concat(c,".").concat(h)]||u[h]||d[h]||o;return n?a.createElement(f,s(s({ref:t},p),{},{components:n})):a.createElement(f,s({ref:t},p))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,s=new Array(o);s[0]=u;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:r,s[1]=i;for(var l=2;l{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var a=n(7462),r=(n(7294),n(3905));const o={sidebar_position:10},s="How to Replay a Contract Instance to the Latest State",i={unversionedId:"advanced/how-to-replay-instance",id:"advanced/how-to-replay-instance",title:"How to Replay a Contract Instance to the Latest State",description:"Using sCrypt Service and sCrypt client, we can effortlessly create a contract instance reflecting the latest state as follows:",source:"@site/docs/advanced/how-to-replay-instance.md",sourceDirName:"advanced",slug:"/advanced/how-to-replay-instance",permalink:"/advanced/how-to-replay-instance",draft:!1,tags:[],version:"current",sidebarPosition:10,frontMatter:{sidebar_position:10},sidebar:"tutorialSidebar",previous:{title:"How to Sign P2PKH Inputs Using the Signer Class",permalink:"/advanced/How to only sign p2pkh inputs"},next:{title:"How to Build an Oracle Service",permalink:"/advanced/how-to-build-an-oracle-service"}},c={},l=[{value:"Step 1. Offchain Helper Functions",id:"step-1-offchain-helper-functions",level:2},{value:"Step 2. Create Instance from Deployment Tx",id:"step-2-create-instance-from-deployment-tx",level:2},{value:"Step 3. Replay Instance to Latest States",id:"step-3-replay-instance-to-latest-states",level:2}],p={toc:l};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"how-to-replay-a-contract-instance-to-the-latest-state"},"How to Replay a Contract Instance to the Latest State"),(0,r.kt)("p",null,"Using ",(0,r.kt)("a",{parentName:"p",href:"/advanced/how-to-integrate-scrypt-service"},"sCrypt Service")," and ",(0,r.kt)("a",{parentName:"p",href:"/advanced/how-to-integrate-scrypt-service#step-1-initialize-client"},"sCrypt client"),", we can effortlessly create a contract instance reflecting the latest state as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"const currentInstance = await Scrypt.contractApi.getLatestInstance(\n Counter,\n contractId\n)\n")),(0,r.kt)("p",null,"However, this method is ineffective for smart contracts with states of type ",(0,r.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#hashedmap"},"HashedMap")," or ",(0,r.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#hashedset"},"HashedSet"),". This is because each instance only contains hashed values, not the original ones."),(0,r.kt)("p",null,"In this section, we'll use ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/sCrypt-Inc/boilerplate/blob/master/src/contracts/crowdfundReplay.ts"},"contract CrowdfundReplay")," located at ",(0,r.kt)("inlineCode",{parentName:"p"},"src/contracts/crowdfundReplay.ts")," as a reference to explain how to replay these contract instances to their latest states."),(0,r.kt)("p",null,"This crowdfund contract features a HashedMap ",(0,r.kt)("inlineCode",{parentName:"p"},"donators")," that records the donors' public key and their respective donation satoshi amounts."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"export type Donators = HashedMap\n\nexport class CrowdfundReplay extends SmartContract {\n \n @prop(true)\n donators: Donators\n \n ...\n}\n")),(0,r.kt)("p",null,"This contract has three public methods:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"donate")," adds an entry to the HashedMap."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"refund")," removes a specific donator from the map."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"collect")," destroys the contract without updating any stateful properties.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"export type Donators = HashedMap\n\nexport class CrowdfundReplay extends SmartContract {\n ...\n\n @method()\n public donate(donator: PubKey, amount: bigint) {\n ...\n assert(!this.donators.has(donator), 'donator already exists')\n this.donators.set(donator, amount)\n ...\n }\n\n @method()\n public refund(donator: PubKey, amount: bigint, sig: Sig) {\n ...\n assert(this.donators.canGet(donator, amount), 'not donated before')\n assert(this.donators.delete(donator), 'failed to remove donator')\n ...\n }\n\n @method()\n public collect(sig: Sig) {\n ...\n }\n}\n")),(0,r.kt)("p",null,"To replay the contract instance to the latest states, follow these three steps:"),(0,r.kt)("h2",{id:"step-1-offchain-helper-functions"},"Step 1. Offchain Helper Functions"),(0,r.kt)("p",null,"Initially, add helper functions that update stateful properties in a manner ",(0,r.kt)("strong",{parentName:"p"},"identical")," to the public methods."),(0,r.kt)("p",null,"These functions are defined within the ",(0,r.kt)("inlineCode",{parentName:"p"},"offchainUpdates")," object:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"class CrowdfundReplay extends SmartContract {\n\n ...\n\n offchainUpdates: OffchainUpdates = {\n 'donate': (next: CrowdfundReplay, donator: PubKey, amount: bigint) => {\n next.donators.set(donator, amount)\n },\n 'refund': (next: CrowdfundReplay, donator: PubKey) => {\n next.donators.delete(donator)\n },\n }\n\n ...\n}\n")),(0,r.kt)("admonition",{type:"note"},(0,r.kt)("p",{parentName:"admonition"},"The object keys must match the public method names precisely.")),(0,r.kt)("p",null,"In our example, we only need two helper functions since the ",(0,r.kt)("inlineCode",{parentName:"p"},"collect")," method doesn't alter any stateful properties."),(0,r.kt)("h2",{id:"step-2-create-instance-from-deployment-tx"},"Step 2. Create Instance from Deployment Tx"),(0,r.kt)("p",null,"Retrieve the deployment transaction using the contract ID. Subsequently, ",(0,r.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#fromtx"},"recover")," the contract instance from it."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"// Recover instance from the deployment transaction\nconst tx = await provider.getTx(contractId.txId)\nconst instance = CrowdfundReplay.fromTx(\n tx,\n contractId.outputIndex,\n {\n donators: new HashedMap(),\n }\n)\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Note"),": For more details on the workings of the ",(0,r.kt)("inlineCode",{parentName:"p"},"fromTx()")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"getTransaction()")," functions, refer to the documentation ",(0,r.kt)("a",{parentName:"p",href:"/how-to-write-a-contract/built-ins#fromtx"},"here"),"."),(0,r.kt)("h2",{id:"step-3-replay-instance-to-latest-states"},"Step 3. Replay Instance to Latest States"),(0,r.kt)("p",null,"Invoke the ",(0,r.kt)("inlineCode",{parentName:"p"},"replayToLatest")," function to acquire the latest contract instance."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"import { replayToLatest } from 'scrypt-ts'\n\n...\n\nconst latestInstance = await replayToLatest(instance, contractId)\n\nif (latestInstance) {\n // The latest instance is now ready for use.\n ...\n}\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Note"),": If the ",(0,r.kt)("inlineCode",{parentName:"p"},"replayToLatest()")," function yields ",(0,r.kt)("inlineCode",{parentName:"p"},"null"),", it indicates that there have been no state changes for the contract instance. This scenario arises if the contract hasn't been interacted with since its deployment or if all state modifications have been reverted."),(0,r.kt)("hr",null))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8c1b62a1.355a5c3f.js b/assets/js/8c1b62a1.355a5c3f.js new file mode 100644 index 000000000..6c761192f --- /dev/null +++ b/assets/js/8c1b62a1.355a5c3f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[55],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>g});var i=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function o(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=i.createContext({}),l=function(e){var t=i.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=l(e.components);return i.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},d=i.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,p=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),d=l(n),g=r,h=d["".concat(p,".").concat(g)]||d[g]||u[g]||a;return n?i.createElement(h,o(o({ref:t},c),{},{components:n})):i.createElement(h,o({ref:t},c))}));function g(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,o=new Array(a);o[0]=d;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var l=2;l{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>o,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>l});var i=n(7462),r=(n(7294),n(3905));const a={sidebar_position:10},o="How to Sign P2PKH Inputs Using the Signer Class",s={unversionedId:"advanced/How to only sign p2pkh inputs",id:"advanced/How to only sign p2pkh inputs",title:"How to Sign P2PKH Inputs Using the Signer Class",description:"In certain scenarios, it is necessary to sign only P2PKH inputs when working with transactions in sCrypt. This documentation will guide you through the process of utilizing the Signer class to achieve this.",source:"@site/docs/advanced/How to only sign p2pkh inputs.md",sourceDirName:"advanced",slug:"/advanced/How to only sign p2pkh inputs",permalink:"/advanced/How to only sign p2pkh inputs",draft:!1,tags:[],version:"current",sidebarPosition:10,frontMatter:{sidebar_position:10},sidebar:"tutorialSidebar",previous:{title:"Time Lock",permalink:"/advanced/timeLock"},next:{title:"How to Replay a Contract Instance to the Latest State",permalink:"/advanced/how-to-replay-instance"}},p={},l=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Implementation",id:"implementation",level:2},{value:"1. Initialize a UTXO for P2PKH",id:"1-initialize-a-utxo-for-p2pkh",level:3},{value:"2. Add the P2PKH UTXO to the Transaction",id:"2-add-the-p2pkh-utxo-to-the-transaction",level:3},{value:"3. Verify Input Script Before Signing",id:"3-verify-input-script-before-signing",level:3},{value:"4. Sign the Transaction",id:"4-sign-the-transaction",level:3},{value:"5. Verify Input Script After Signing",id:"5-verify-input-script-after-signing",level:3},{value:"Example Implementation",id:"example-implementation",level:3},{value:"Conclusion",id:"conclusion",level:2}],c={toc:l};function u(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,i.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"how-to-sign-p2pkh-inputs-using-the-signer-class"},"How to Sign P2PKH Inputs Using the Signer Class"),(0,r.kt)("p",null,"In certain scenarios, it is necessary to sign only P2PKH inputs when working with transactions in sCrypt. This documentation will guide you through the process of utilizing the ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Signer"))," class to achieve this."),(0,r.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("p",null,"Before proceeding, make sure you have a basic understanding of the sCrypt. library and have set up the required dependencies."),(0,r.kt)("h2",{id:"implementation"},"Implementation"),(0,r.kt)("h3",{id:"1-initialize-a-utxo-for-p2pkh"},"1. Initialize a UTXO for P2PKH"),(0,r.kt)("p",null,"Start by defining a P2PKH Unspent Transaction Output (UTXO) that you intend to use for your transaction:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"const utxo = {\n txId: '5260b12348608a33c2ac90ed8a08e0b3eb90bbe862bcea6b21b1f29f1c2fdee0',\n outputIndex: 0,\n script: bsv.Script.fromASM('OP_DUP OP_HASH160 af838fed6517e595e6761c2b96849bec473b00f8 OP_EQUALVERIFY OP_CHECKSIG').toHex(),\n satoshis: 1000,\n};\n")),(0,r.kt)("h3",{id:"2-add-the-p2pkh-utxo-to-the-transaction"},"2. Add the P2PKH UTXO to the Transaction"),(0,r.kt)("p",null,"Use the from() method to add the P2PKH UTXO to your transaction. This marks the input as a P2PKH input:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"tx.from(utxo);\n")),(0,r.kt)("h3",{id:"3-verify-input-script-before-signing"},"3. Verify Input Script Before Signing"),(0,r.kt)("p",null,"Before signing the transaction, ensure that the input script is empty. This can be done with the following code:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"console.log(tx.inputs[2].script.toASM()); // Empty, no signature\n")),(0,r.kt)("h3",{id:"4-sign-the-transaction"},"4. Sign the Transaction"),(0,r.kt)("p",null,"Use the Signer class to sign the transaction:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"const signer = getDefaultSigner();\nawait signer.signTransaction(tx);\n")),(0,r.kt)("h3",{id:"5-verify-input-script-after-signing"},"5. Verify Input Script After Signing"),(0,r.kt)("p",null,"After signing, confirm that the input script now contains the signature and public key:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"console.log(tx.inputs[2].script.toASM()); // Should contain signature and pubkey\n")),(0,r.kt)("h3",{id:"example-implementation"},"Example Implementation"),(0,r.kt)("p",null,"Here is a simplified example demonstrating the steps above within a transaction :"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"const tx = new bsv.Transaction();\n// Add inputs, outputs, and other transaction details as needed\n\n// Add P2PKH UTXO\ntx.from(utxo);\n\n// Verify input script before signing\nconsole.log(tx.inputs[2].script.toASM()); // Empty, no signature\n\n// Sign the transaction\nconst signer = getDefaultSigner();\nawait signer.signTransaction(tx);\n\n// Verify input script after signing\nconsole.log(tx.inputs[2].script.toASM()); // Should contain signature and pubkey\n\n.................................\n.................................\n\n// Finalize the transaction\nconst finalizedTx = tx.build();\n")),(0,r.kt)("h2",{id:"conclusion"},"Conclusion"),(0,r.kt)("p",null,"By following these steps, your transaction sign only P2PKH inputs using the ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Signer"))," class in sCrypt. If you encounter any issues or have specific requirements,\nplease refer to the ",(0,r.kt)("a",{parentName:"p",href:"https://app.slack.com/client/TLSHKFH5Y/CLSHPUZC3"},"sCrypt slack channel")," to seek further assistance."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.5566804d.js b/assets/js/935f2afb.5566804d.js deleted file mode 100644 index 907e426e3..000000000 --- a/assets/js/935f2afb.5566804d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"tutorialSidebar":[{"type":"link","label":"Overview","href":"/","docId":"overview"},{"type":"link","label":"Installation","href":"/installation","docId":"installation"},{"type":"category","label":"Bitcoin Basics","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"The BSV submodule","href":"/bitcoin-basics/bsv","docId":"bitcoin-basics/bsv"}],"href":"/bitcoin-basics/"},{"type":"category","label":"How to Write a Contract","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ScriptContext","href":"/how-to-write-a-contract/scriptcontext","docId":"how-to-write-a-contract/scriptcontext"},{"type":"link","label":"Stateful Contracts","href":"/how-to-write-a-contract/stateful-contract","docId":"how-to-write-a-contract/stateful-contract"},{"type":"link","label":"Built-ins","href":"/how-to-write-a-contract/built-ins","docId":"how-to-write-a-contract/built-ins"}],"href":"/how-to-write-a-contract/"},{"type":"category","label":"How to Deploy & Call a Contract","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How to Customize a Contract Tx","href":"/how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx","docId":"how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx"},{"type":"link","label":"Deploy Using CLI","href":"/how-to-deploy-and-call-a-contract/deploy-cli","docId":"how-to-deploy-and-call-a-contract/deploy-cli"},{"type":"link","label":"Faucet","href":"/how-to-deploy-and-call-a-contract/faucet","docId":"how-to-deploy-and-call-a-contract/faucet"},{"type":"link","label":"Interact with a Deployed Contract","href":"/how-to-deploy-and-call-a-contract/call-deployed","docId":"how-to-deploy-and-call-a-contract/call-deployed"}],"href":"/how-to-deploy-and-call-a-contract/"},{"type":"link","label":"How to Test a Contract","href":"/how-to-test-a-contract","docId":"how-to-test-a-contract"},{"type":"link","label":"How to Debug a Contract","href":"/how-to-debug-a-contract","docId":"how-to-debug-a-contract"},{"type":"category","label":"How to Integrate With a Frontend","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How to integrate DotWallet","href":"/how-to-integrate-a-frontend/how-to-integrate-dotwallet","docId":"how-to-integrate-a-frontend/how-to-integrate-dotwallet"}],"href":"/how-to-integrate-a-frontend/"},{"type":"link","label":"How to Publish a Contract to NPM","href":"/how-to-publish-a-contract","docId":"how-to-publish-a-contract"},{"type":"link","label":"How to Verify a Contract","href":"/how-to-verify-a-contract","docId":"how-to-verify-a-contract"},{"type":"link","label":"sCrypt for Ethereum Developers","href":"/ethereum-devs","docId":"ethereum-devs"},{"type":"category","label":"Advanced","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How to Integrate sCrypt Service","href":"/advanced/how-to-integrate-scrypt-service","docId":"advanced/how-to-integrate-scrypt-service"},{"type":"link","label":"Sighash Types","href":"/advanced/sighash-type","docId":"advanced/sighash-type"},{"type":"link","label":"How to Debug ScriptContext Failure","href":"/advanced/how-to-debug-scriptcontext","docId":"advanced/how-to-debug-scriptcontext"},{"type":"link","label":"Use Script inside sCrypt","href":"/advanced/inline-asm","docId":"advanced/inline-asm"},{"type":"link","label":"Use Code Separators","href":"/advanced/codeseparator","docId":"advanced/codeseparator"},{"type":"link","label":"How to Add a Provider","href":"/advanced/how-to-add-a-provider","docId":"advanced/how-to-add-a-provider"},{"type":"link","label":"How to Add a Signer","href":"/advanced/how-to-add-a-signer","docId":"advanced/how-to-add-a-signer"},{"type":"link","label":"Call Multiple Contracts in a Single Tx","href":"/advanced/how-to-call-multiple-contracts","docId":"advanced/how-to-call-multiple-contracts"},{"type":"link","label":"Time Lock","href":"/advanced/timeLock","docId":"advanced/timeLock"},{"type":"link","label":"How to Replay a Contract Instance to the Latest State","href":"/advanced/how-to-replay-instance","docId":"advanced/how-to-replay-instance"},{"type":"link","label":"How to Build an Oracle Service","href":"/advanced/how-to-build-an-oracle-service","docId":"advanced/how-to-build-an-oracle-service"}],"href":"/category/advanced"},{"type":"category","label":"Tokens","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Non Fungible Tokens - NFTs","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Transfer Existing NFT to a Smart Contract","href":"/tokens/nft/existing","docId":"tokens/nft/existing"}],"href":"/tokens/nft/"},{"type":"category","label":"Fungible Tokens - FTs","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Transfer Existing FT to a Smart Contract","href":"/tokens/ft/existing","docId":"tokens/ft/existing"},{"type":"link","label":"Multiple Inputs with Different Contracts","href":"/tokens/ft/multiple","docId":"tokens/ft/multiple"},{"type":"link","label":"View BSV20 Token Transactions","href":"/tokens/ft/woc-bsv20-plugin","docId":"tokens/ft/woc-bsv20-plugin"}],"href":"/tokens/ft/"},{"type":"category","label":"Tutorials","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Tutorial 1: Inscribe Image","href":"/tokens/tutorials/inscribe-image","docId":"tokens/tutorials/inscribe-image"},{"type":"link","label":"Tutorial 2: Mint BSV20 V2 Token","href":"/tokens/tutorials/mint-bsv20-v2","docId":"tokens/tutorials/mint-bsv20-v2"},{"type":"link","label":"Tutorial 3: Mint BSV20 V1 Token","href":"/tokens/tutorials/mint-bsv20-v1","docId":"tokens/tutorials/mint-bsv20-v1"},{"type":"link","label":"Tutorial 4: Ordinal Lock","href":"/tokens/tutorials/ordinal-lock","docId":"tokens/tutorials/ordinal-lock"}],"href":"/category/tutorials"}],"href":"/tokens/"},{"type":"category","label":"Tutorials","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Tutorial 1: Hello World","href":"/tutorials/hello-world","docId":"tutorials/hello-world"},{"type":"link","label":"Tutorial 2: Auction","href":"/tutorials/auction","docId":"tutorials/auction"},{"type":"link","label":"Tutorial 3: Oracle","href":"/tutorials/oracle","docId":"tutorials/oracle"},{"type":"link","label":"Tutorial 4: Tic Tac Toe","href":"/tutorials/tic-tac-toe","docId":"tutorials/tic-tac-toe"},{"type":"link","label":"Tutorial 5: Zero Knowledge Proofs","href":"/tutorials/zkp","docId":"tutorials/zkp"},{"type":"link","label":"Tutorial 6: Voting","href":"/tutorials/voting","docId":"tutorials/voting"},{"type":"link","label":"Tutorial 7: Escrow","href":"/tutorials/escrow","docId":"tutorials/escrow"}],"href":"/category/tutorials-1"},{"type":"link","label":"FAQ","href":"/faq","docId":"faq"},{"type":"category","label":"Reference","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"classes","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ActionError","href":"/reference/classes/ActionError","docId":"reference/classes/ActionError"},{"type":"link","label":"BsvApi","href":"/reference/classes/BsvApi","docId":"reference/classes/BsvApi"},{"type":"link","label":"Constants","href":"/reference/classes/Constants","docId":"reference/classes/Constants"},{"type":"link","label":"ContractApi","href":"/reference/classes/ContractApi","docId":"reference/classes/ContractApi"},{"type":"link","label":"DefaultProvider","href":"/reference/classes/DefaultProvider","docId":"reference/classes/DefaultProvider"},{"type":"link","label":"DotwalletSigner","href":"/reference/classes/DotwalletSigner","docId":"reference/classes/DotwalletSigner"},{"type":"link","label":"DummyProvider","href":"/reference/classes/DummyProvider","docId":"reference/classes/DummyProvider"},{"type":"link","label":"FunctionCall","href":"/reference/classes/FunctionCall","docId":"reference/classes/FunctionCall"},{"type":"link","label":"GorillapoolProvider","href":"/reference/classes/GorillapoolProvider","docId":"reference/classes/GorillapoolProvider"},{"type":"link","label":"HashedMap","href":"/reference/classes/HashedMap","docId":"reference/classes/HashedMap"},{"type":"link","label":"HashedSet","href":"/reference/classes/HashedSet","docId":"reference/classes/HashedSet"},{"type":"link","label":"OpCode","href":"/reference/classes/OpCode","docId":"reference/classes/OpCode"},{"type":"link","label":"Provider","href":"/reference/classes/Provider","docId":"reference/classes/Provider"},{"type":"link","label":"ScryptProvider","href":"/reference/classes/ScryptProvider","docId":"reference/classes/ScryptProvider"},{"type":"link","label":"SensibleProvider","href":"/reference/classes/SensibleProvider","docId":"reference/classes/SensibleProvider"},{"type":"link","label":"SensiletSigner","href":"/reference/classes/SensiletSigner","docId":"reference/classes/SensiletSigner"},{"type":"link","label":"SigHash","href":"/reference/classes/SigHash","docId":"reference/classes/SigHash"},{"type":"link","label":"Signer","href":"/reference/classes/Signer","docId":"reference/classes/Signer"},{"type":"link","label":"SmartContract","href":"/reference/classes/SmartContract","docId":"reference/classes/SmartContract"},{"type":"link","label":"SmartContractLib","href":"/reference/classes/SmartContractLib","docId":"reference/classes/SmartContractLib"},{"type":"link","label":"TAALSigner","href":"/reference/classes/TAALSigner","docId":"reference/classes/TAALSigner"},{"type":"link","label":"TaalProvider","href":"/reference/classes/TaalProvider","docId":"reference/classes/TaalProvider"},{"type":"link","label":"TestWallet","href":"/reference/classes/TestWallet","docId":"reference/classes/TestWallet"},{"type":"link","label":"Utils","href":"/reference/classes/Utils","docId":"reference/classes/Utils"},{"type":"link","label":"VarIntReader","href":"/reference/classes/VarIntReader","docId":"reference/classes/VarIntReader"},{"type":"link","label":"VarIntWriter","href":"/reference/classes/VarIntWriter","docId":"reference/classes/VarIntWriter"},{"type":"link","label":"WhatsonchainProvider","href":"/reference/classes/WhatsonchainProvider","docId":"reference/classes/WhatsonchainProvider"},{"type":"link","label":"bsv.Address","href":"/reference/classes/bsv.Address","docId":"reference/classes/bsv.Address"},{"type":"link","label":"bsv.Block","href":"/reference/classes/bsv.Block","docId":"reference/classes/bsv.Block"},{"type":"link","label":"bsv.BlockHeader","href":"/reference/classes/bsv.BlockHeader","docId":"reference/classes/bsv.BlockHeader"},{"type":"link","label":"bsv.ECIES","href":"/reference/classes/bsv.ECIES","docId":"reference/classes/bsv.ECIES"},{"type":"link","label":"bsv.HDPrivateKey","href":"/reference/classes/bsv.HDPrivateKey","docId":"reference/classes/bsv.HDPrivateKey"},{"type":"link","label":"bsv.HDPublicKey","href":"/reference/classes/bsv.HDPublicKey","docId":"reference/classes/bsv.HDPublicKey"},{"type":"link","label":"bsv.MerkleBlock","href":"/reference/classes/bsv.MerkleBlock","docId":"reference/classes/bsv.MerkleBlock"},{"type":"link","label":"bsv.Message","href":"/reference/classes/bsv.Message","docId":"reference/classes/bsv.Message"},{"type":"link","label":"bsv.Mnemonic","href":"/reference/classes/bsv.Mnemonic","docId":"reference/classes/bsv.Mnemonic"},{"type":"link","label":"bsv.Opcode","href":"/reference/classes/bsv.Opcode","docId":"reference/classes/bsv.Opcode"},{"type":"link","label":"bsv.PrivateKey","href":"/reference/classes/bsv.PrivateKey","docId":"reference/classes/bsv.PrivateKey"},{"type":"link","label":"bsv.PublicKey","href":"/reference/classes/bsv.PublicKey","docId":"reference/classes/bsv.PublicKey"},{"type":"link","label":"bsv.Script-1","href":"/reference/classes/bsv.Script-1","docId":"reference/classes/bsv.Script-1"},{"type":"link","label":"bsv.Script.Interpreter-1","href":"/reference/classes/bsv.Script.Interpreter-1","docId":"reference/classes/bsv.Script.Interpreter-1"},{"type":"link","label":"bsv.Transaction-1","href":"/reference/classes/bsv.Transaction-1","docId":"reference/classes/bsv.Transaction-1"},{"type":"link","label":"bsv.Transaction.Input-1","href":"/reference/classes/bsv.Transaction.Input-1","docId":"reference/classes/bsv.Transaction.Input-1"},{"type":"link","label":"bsv.Transaction.Input.PublicKeyHash","href":"/reference/classes/bsv.Transaction.Input.PublicKeyHash","docId":"reference/classes/bsv.Transaction.Input.PublicKeyHash"},{"type":"link","label":"bsv.Transaction.Output","href":"/reference/classes/bsv.Transaction.Output","docId":"reference/classes/bsv.Transaction.Output"},{"type":"link","label":"bsv.Transaction.Signature","href":"/reference/classes/bsv.Transaction.Signature","docId":"reference/classes/bsv.Transaction.Signature"},{"type":"link","label":"bsv.Transaction.UnspentOutput","href":"/reference/classes/bsv.Transaction.UnspentOutput","docId":"reference/classes/bsv.Transaction.UnspentOutput"},{"type":"link","label":"bsv.Unit","href":"/reference/classes/bsv.Unit","docId":"reference/classes/bsv.Unit"},{"type":"link","label":"bsv.crypto.BN","href":"/reference/classes/bsv.crypto.BN","docId":"reference/classes/bsv.crypto.BN"},{"type":"link","label":"bsv.crypto.Point","href":"/reference/classes/bsv.crypto.Point","docId":"reference/classes/bsv.crypto.Point"},{"type":"link","label":"bsv.crypto.Signature","href":"/reference/classes/bsv.crypto.Signature","docId":"reference/classes/bsv.crypto.Signature"},{"type":"link","label":"bsv.encoding.Base58","href":"/reference/classes/bsv.encoding.Base58","docId":"reference/classes/bsv.encoding.Base58"},{"type":"link","label":"bsv.encoding.Base58Check","href":"/reference/classes/bsv.encoding.Base58Check","docId":"reference/classes/bsv.encoding.Base58Check"},{"type":"link","label":"bsv.encoding.BufferReader","href":"/reference/classes/bsv.encoding.BufferReader","docId":"reference/classes/bsv.encoding.BufferReader"},{"type":"link","label":"bsv.encoding.BufferWriter","href":"/reference/classes/bsv.encoding.BufferWriter","docId":"reference/classes/bsv.encoding.BufferWriter"},{"type":"link","label":"bsv.encoding.Varint","href":"/reference/classes/bsv.encoding.Varint","docId":"reference/classes/bsv.encoding.Varint"}]},{"type":"category","label":"enums","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ProviderEvent","href":"/reference/enums/ProviderEvent","docId":"reference/enums/ProviderEvent"},{"type":"link","label":"SignatureHashType","href":"/reference/enums/SignatureHashType","docId":"reference/enums/SignatureHashType"}]},{"type":"category","label":"interfaces","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Artifact","href":"/reference/interfaces/Artifact","docId":"reference/interfaces/Artifact"},{"type":"link","label":"ContractCalledEvent","href":"/reference/interfaces/ContractCalledEvent","docId":"reference/interfaces/ContractCalledEvent"},{"type":"link","label":"ContractTransaction","href":"/reference/interfaces/ContractTransaction","docId":"reference/interfaces/ContractTransaction"},{"type":"link","label":"DefaultProviderOption","href":"/reference/interfaces/DefaultProviderOption","docId":"reference/interfaces/DefaultProviderOption"},{"type":"link","label":"LogConfig","href":"/reference/interfaces/LogConfig","docId":"reference/interfaces/LogConfig"},{"type":"link","label":"MethodCallOptions","href":"/reference/interfaces/MethodCallOptions","docId":"reference/interfaces/MethodCallOptions"},{"type":"link","label":"MethodCallTxBuilder","href":"/reference/interfaces/MethodCallTxBuilder","docId":"reference/interfaces/MethodCallTxBuilder"},{"type":"link","label":"MultiContractCallOptions","href":"/reference/interfaces/MultiContractCallOptions","docId":"reference/interfaces/MultiContractCallOptions"},{"type":"link","label":"MultiContractTransaction","href":"/reference/interfaces/MultiContractTransaction","docId":"reference/interfaces/MultiContractTransaction"},{"type":"link","label":"Outpoint","href":"/reference/interfaces/Outpoint","docId":"reference/interfaces/Outpoint"},{"type":"link","label":"RequestConfig","href":"/reference/interfaces/RequestConfig","docId":"reference/interfaces/RequestConfig"},{"type":"link","label":"ScriptContext","href":"/reference/interfaces/ScriptContext","docId":"reference/interfaces/ScriptContext"},{"type":"link","label":"ScryptConfig","href":"/reference/interfaces/ScryptConfig","docId":"reference/interfaces/ScryptConfig"},{"type":"link","label":"SignTransactionOptions","href":"/reference/interfaces/SignTransactionOptions","docId":"reference/interfaces/SignTransactionOptions"},{"type":"link","label":"SignatureRequest","href":"/reference/interfaces/SignatureRequest","docId":"reference/interfaces/SignatureRequest"},{"type":"link","label":"SignatureResponse","href":"/reference/interfaces/SignatureResponse","docId":"reference/interfaces/SignatureResponse"},{"type":"link","label":"StatefulNext","href":"/reference/interfaces/StatefulNext","docId":"reference/interfaces/StatefulNext"},{"type":"link","label":"SubScription","href":"/reference/interfaces/SubScription","docId":"reference/interfaces/SubScription"},{"type":"link","label":"SubscribeOptions","href":"/reference/interfaces/SubscribeOptions","docId":"reference/interfaces/SubscribeOptions"},{"type":"link","label":"TransactionResponse","href":"/reference/interfaces/TransactionResponse","docId":"reference/interfaces/TransactionResponse"},{"type":"link","label":"TxContext","href":"/reference/interfaces/TxContext","docId":"reference/interfaces/TxContext"},{"type":"link","label":"TxInputRef","href":"/reference/interfaces/TxInputRef","docId":"reference/interfaces/TxInputRef"},{"type":"link","label":"TxOutputRef","href":"/reference/interfaces/TxOutputRef","docId":"reference/interfaces/TxOutputRef"},{"type":"link","label":"UtxoQueryOptions","href":"/reference/interfaces/UtxoQueryOptions","docId":"reference/interfaces/UtxoQueryOptions"},{"type":"link","label":"VerifyResult","href":"/reference/interfaces/VerifyResult","docId":"reference/interfaces/VerifyResult"},{"type":"link","label":"bsv.Networks.Network","href":"/reference/interfaces/bsv.Networks.Network","docId":"reference/interfaces/bsv.Networks.Network"},{"type":"link","label":"bsv.Script.IOpChunk","href":"/reference/interfaces/bsv.Script.IOpChunk","docId":"reference/interfaces/bsv.Script.IOpChunk"},{"type":"link","label":"bsv.Script.Interpreter.InterpretState","href":"/reference/interfaces/bsv.Script.Interpreter.InterpretState","docId":"reference/interfaces/bsv.Script.Interpreter.InterpretState"},{"type":"link","label":"bsv.Transaction.IUnspentOutput","href":"/reference/interfaces/bsv.Transaction.IUnspentOutput","docId":"reference/interfaces/bsv.Transaction.IUnspentOutput"},{"type":"link","label":"bsv.Util","href":"/reference/interfaces/bsv.Util","docId":"reference/interfaces/bsv.Util"},{"type":"link","label":"bsv.crypto.IOpts","href":"/reference/interfaces/bsv.crypto.IOpts","docId":"reference/interfaces/bsv.crypto.IOpts"}]},{"type":"category","label":"modules","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"bsv.Networks","href":"/reference/modules/bsv.Networks","docId":"reference/modules/bsv.Networks"},{"type":"link","label":"bsv.Script.Interpreter","href":"/reference/modules/bsv.Script.Interpreter","docId":"reference/modules/bsv.Script.Interpreter"},{"type":"link","label":"bsv.Script","href":"/reference/modules/bsv.Script","docId":"reference/modules/bsv.Script"},{"type":"link","label":"bsv.Transaction.Input","href":"/reference/modules/bsv.Transaction.Input","docId":"reference/modules/bsv.Transaction.Input"},{"type":"link","label":"bsv.Transaction.Sighash","href":"/reference/modules/bsv.Transaction.Sighash","docId":"reference/modules/bsv.Transaction.Sighash"},{"type":"link","label":"bsv.Transaction","href":"/reference/modules/bsv.Transaction","docId":"reference/modules/bsv.Transaction"},{"type":"link","label":"bsv.crypto.ECDSA","href":"/reference/modules/bsv.crypto.ECDSA","docId":"reference/modules/bsv.crypto.ECDSA"},{"type":"link","label":"bsv.crypto.Hash","href":"/reference/modules/bsv.crypto.Hash","docId":"reference/modules/bsv.crypto.Hash"},{"type":"link","label":"bsv.crypto.Random","href":"/reference/modules/bsv.crypto.Random","docId":"reference/modules/bsv.crypto.Random"},{"type":"link","label":"bsv.crypto","href":"/reference/modules/bsv.crypto","docId":"reference/modules/bsv.crypto"},{"type":"link","label":"bsv.encoding","href":"/reference/modules/bsv.encoding","docId":"reference/modules/bsv.encoding"},{"type":"link","label":"bsv","href":"/reference/modules/bsv","docId":"reference/modules/bsv"}]}],"href":"/reference/"}]},"docs":{"advanced/codeseparator":{"id":"advanced/codeseparator","title":"Use Code Separators","description":"How Code Separators Work","sidebar":"tutorialSidebar"},"advanced/how-to-add-a-provider":{"id":"advanced/how-to-add-a-provider","title":"How to Add a Provider","description":"In the contract testing section, we learned about the Provider class in sCrypt. This class serves as an abstraction of a Bitcoin node, allowing your application to communicate with the Bitcoin network.","sidebar":"tutorialSidebar"},"advanced/how-to-add-a-signer":{"id":"advanced/how-to-add-a-signer","title":"How to Add a Signer","description":"As described in this section, a signer is an abstraction of private keys, which can be used to sign messages and transactions. A simple signer would be a single private key, while a complex signer is a wallet.","sidebar":"tutorialSidebar"},"advanced/how-to-build-an-oracle-service":{"id":"advanced/how-to-build-an-oracle-service","title":"How to Build an Oracle Service","description":"As described in this tutorial, a blockchain oracle is a third-party service or agent that provides external data to a blockchain network. It is a bridge between the blockchain and the external world, enabling smart contracts to access, verify, and incorporate data from outside the blockchain. Specifically, the oracle service provides external data along with a Rabin signature of the data, and the smart contract uses this data and verifies the signature before using it.","sidebar":"tutorialSidebar"},"advanced/how-to-call-multiple-contracts":{"id":"advanced/how-to-call-multiple-contracts","title":"Call Multiple Contracts in a Single Tx","description":"Up to now, we have only shown how to call one smart contract in a transaction. That is, only one input of the tx spends a smart contract UTXO, and the other inputs, if any, spend Pay-to-Public-Key-Hash (P2PKH) UTXOs, which are generally NOT regarded as smart contracts.","sidebar":"tutorialSidebar"},"advanced/how-to-debug-scriptcontext":{"id":"advanced/how-to-debug-scriptcontext","title":"How to Debug ScriptContext Failure","description":"ScriptContext enables the logic of the contract to be executed correctly according to the agreement, and the state of the contract to be propagated correctly.","sidebar":"tutorialSidebar"},"advanced/how-to-integrate-scrypt-service":{"id":"advanced/how-to-integrate-scrypt-service","title":"How to Integrate sCrypt Service","description":"Before interacting with a sCrypt contract, we must create a contract instance representing the latest state of the contract on chain. Such an instance can be created by calling the fromTx method. However, this means your application needs to track and record all contract-related transactions, especially for a stateful contract.","sidebar":"tutorialSidebar"},"advanced/how-to-replay-instance":{"id":"advanced/how-to-replay-instance","title":"How to Replay a Contract Instance to the Latest State","description":"Using sCrypt Service and sCrypt client, we can effortlessly create a contract instance reflecting the latest state as follows:","sidebar":"tutorialSidebar"},"advanced/inline-asm":{"id":"advanced/inline-asm","title":"Use Script inside sCrypt","description":"Script is a low-level language and acts as assembly for the Bitcoin Virtual Machine. Usually, developers do not have to deal with it directly and can use high-level languages like sCrypt. However, there are cases where using script is desirable. For example, customized script is optimized and thus smaller and more efficient than Script generated by sCrypt. Or script is generated using external tools like Baguette and needs to be integrated into sCrypt.","sidebar":"tutorialSidebar"},"advanced/sighash-type":{"id":"advanced/sighash-type","title":"Sighash Types","description":"A signature hash (sighash) flag is used to indicate which part of the transaction is signed by the ECDSA signature. There are mainly two ways to use it in the context of Bitcoin smart contracts.","sidebar":"tutorialSidebar"},"advanced/timeLock":{"id":"advanced/timeLock","title":"Time Lock","description":"Overview","sidebar":"tutorialSidebar"},"bitcoin-basics/bitcoin-basics":{"id":"bitcoin-basics/bitcoin-basics","title":"Bitcoin Basics","description":"If you are new to Bitcoin development, we recommend exploring the resources listed in this section. While not an absolute prerequisite, going over these guides will provide a clearer understanding of key concepts and make it easier to begin developing sCrypt smart contracts.","sidebar":"tutorialSidebar"},"bitcoin-basics/bsv":{"id":"bitcoin-basics/bsv","title":"The BSV submodule","description":"sCrypt exports a submodule named bsv which is an interface that helps you manage low-level things for the Bitcoin blockchain, such as creating key pairs, building, signing and serializing Bitcoin transactions and more.","sidebar":"tutorialSidebar"},"ethereum-devs":{"id":"ethereum-devs","title":"sCrypt for Ethereum Developers","description":"Bitcoin and Ethereum are both layer-1 blockchains with fully programmable smart contracts.","sidebar":"tutorialSidebar"},"faq":{"id":"faq","title":"FAQ","description":"Smart contract call failure","sidebar":"tutorialSidebar"},"how-to-debug-a-contract":{"id":"how-to-debug-a-contract","title":"How to Debug a Contract","description":"Debugging an sCrypt contract is as easy as debugging TypeScript, since it is just TypeScript.","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/call-deployed":{"id":"how-to-deploy-and-call-a-contract/call-deployed","title":"Interact with a Deployed Contract","description":"Overview","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/deploy-cli":{"id":"how-to-deploy-and-call-a-contract/deploy-cli","title":"Deploy Using CLI","description":"The deploy command allows you to deploy an instance of a smart contract to the blockchain. You can simply run the following command in the root of an sCrypt project:","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/faucet":{"id":"how-to-deploy-and-call-a-contract/faucet","title":"Faucet","description":"It is highly recommended to test your contract on the testnet after passing local tests. It ensures that a contract can be successfully deployed and invoked as expected on the blockchain.","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx":{"id":"how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx","title":"How to Customize a Contract Tx","description":"Deployment Tx","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/how-to-deploy-and-call-a-contract":{"id":"how-to-deploy-and-call-a-contract/how-to-deploy-and-call-a-contract","title":"How to Deploy & Call a Contract","description":"Core Concepts","sidebar":"tutorialSidebar"},"how-to-integrate-a-frontend/how-to-integrate-a-frontend":{"id":"how-to-integrate-a-frontend/how-to-integrate-a-frontend","title":"How to Integrate With a Frontend","description":"This section will show how to integrate your smart contract to a frontend, so users can interact with it.","sidebar":"tutorialSidebar"},"how-to-integrate-a-frontend/how-to-integrate-dotwallet":{"id":"how-to-integrate-a-frontend/how-to-integrate-dotwallet","title":"How to integrate DotWallet","description":"DotWallet is a lightweight wallet designed to help users easily and securely manage their digital assets. We will show how to integrate it with sCrypt-powered apps.","sidebar":"tutorialSidebar"},"how-to-publish-a-contract":{"id":"how-to-publish-a-contract","title":"How to Publish a Contract to NPM","description":"What is a Smart Contract Library?","sidebar":"tutorialSidebar"},"how-to-test-a-contract":{"id":"how-to-test-a-contract","title":"How to Test a Contract","description":"Before using a smart contract in production, one should always test it carefully, especially because any bug in it may cause real economic losses.","sidebar":"tutorialSidebar"},"how-to-verify-a-contract":{"id":"how-to-verify-a-contract","title":"How to Verify a Contract","description":"You will learn how to verify smart contracts on WhatsOnChain (WoC), a blockchain explorer.","sidebar":"tutorialSidebar"},"how-to-write-a-contract/built-ins":{"id":"how-to-write-a-contract/built-ins","title":"Built-ins","description":"Global Functions","sidebar":"tutorialSidebar"},"how-to-write-a-contract/how-to-write-a-contract":{"id":"how-to-write-a-contract/how-to-write-a-contract","title":"How to Write a Contract","description":"A smart contract is a class that extends the SmartContract base class. A simple example is shown below.","sidebar":"tutorialSidebar"},"how-to-write-a-contract/scriptcontext":{"id":"how-to-write-a-contract/scriptcontext","title":"ScriptContext","description":"In the UTXO model, the context of validating a smart contract is the UTXO containing it and the transaction spending it, including its inputs and outputs. In the following example, when the second of input of transaction tx1 (2 inputs and 2 outputs) is spending the second output of tx0 (3 inputs and 3 outputs), the context for the smart contract in the latter output is roughly the UTXO and tx1 circled in red.","sidebar":"tutorialSidebar"},"how-to-write-a-contract/stateful-contract":{"id":"how-to-write-a-contract/stateful-contract","title":"Stateful Contracts","description":"Overview","sidebar":"tutorialSidebar"},"installation":{"id":"installation","title":"Installation","description":"Prerequisite","sidebar":"tutorialSidebar"},"overview":{"id":"overview","title":"Overview","description":"sCrypt is an embedded Domain Specific Language (eDSL) based on TypeScript for writing smart contracts on Bitcoin SV. Embedded means that it is a language inside another language. sCrypt is strictly a subset of TypeScript, so all sCrypt code is valid TypeScript, but not vice versa.","sidebar":"tutorialSidebar"},"reference/classes/ActionError":{"id":"reference/classes/ActionError","title":"ActionError","description":"scrypt-ts / ActionError","sidebar":"tutorialSidebar"},"reference/classes/bsv.Address":{"id":"reference/classes/bsv.Address","title":"bsv.Address","description":"scrypt-ts / bsv / Address","sidebar":"tutorialSidebar"},"reference/classes/bsv.Block":{"id":"reference/classes/bsv.Block","title":"bsv.Block","description":"scrypt-ts / bsv / Block","sidebar":"tutorialSidebar"},"reference/classes/bsv.BlockHeader":{"id":"reference/classes/bsv.BlockHeader","title":"bsv.BlockHeader","description":"scrypt-ts / bsv / BlockHeader","sidebar":"tutorialSidebar"},"reference/classes/bsv.crypto.BN":{"id":"reference/classes/bsv.crypto.BN","title":"bsv.crypto.BN","description":"scrypt-ts / bsv / crypto / BN","sidebar":"tutorialSidebar"},"reference/classes/bsv.crypto.Point":{"id":"reference/classes/bsv.crypto.Point","title":"bsv.crypto.Point","description":"scrypt-ts / bsv / crypto / Point","sidebar":"tutorialSidebar"},"reference/classes/bsv.crypto.Signature":{"id":"reference/classes/bsv.crypto.Signature","title":"bsv.crypto.Signature","description":"scrypt-ts / bsv / crypto / Signature","sidebar":"tutorialSidebar"},"reference/classes/bsv.ECIES":{"id":"reference/classes/bsv.ECIES","title":"bsv.ECIES","description":"scrypt-ts / bsv / ECIES","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.Base58":{"id":"reference/classes/bsv.encoding.Base58","title":"bsv.encoding.Base58","description":"scrypt-ts / bsv / encoding / Base58","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.Base58Check":{"id":"reference/classes/bsv.encoding.Base58Check","title":"bsv.encoding.Base58Check","description":"scrypt-ts / bsv / encoding / Base58Check","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.BufferReader":{"id":"reference/classes/bsv.encoding.BufferReader","title":"bsv.encoding.BufferReader","description":"scrypt-ts / bsv / encoding / BufferReader","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.BufferWriter":{"id":"reference/classes/bsv.encoding.BufferWriter","title":"bsv.encoding.BufferWriter","description":"scrypt-ts / bsv / encoding / BufferWriter","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.Varint":{"id":"reference/classes/bsv.encoding.Varint","title":"bsv.encoding.Varint","description":"scrypt-ts / bsv / encoding / Varint","sidebar":"tutorialSidebar"},"reference/classes/bsv.HDPrivateKey":{"id":"reference/classes/bsv.HDPrivateKey","title":"bsv.HDPrivateKey","description":"scrypt-ts / bsv / HDPrivateKey","sidebar":"tutorialSidebar"},"reference/classes/bsv.HDPublicKey":{"id":"reference/classes/bsv.HDPublicKey","title":"bsv.HDPublicKey","description":"scrypt-ts / bsv / HDPublicKey","sidebar":"tutorialSidebar"},"reference/classes/bsv.MerkleBlock":{"id":"reference/classes/bsv.MerkleBlock","title":"bsv.MerkleBlock","description":"scrypt-ts / bsv / MerkleBlock","sidebar":"tutorialSidebar"},"reference/classes/bsv.Message":{"id":"reference/classes/bsv.Message","title":"bsv.Message","description":"scrypt-ts / bsv / Message","sidebar":"tutorialSidebar"},"reference/classes/bsv.Mnemonic":{"id":"reference/classes/bsv.Mnemonic","title":"bsv.Mnemonic","description":"scrypt-ts / bsv / Mnemonic","sidebar":"tutorialSidebar"},"reference/classes/bsv.Opcode":{"id":"reference/classes/bsv.Opcode","title":"bsv.Opcode","description":"scrypt-ts / bsv / Opcode","sidebar":"tutorialSidebar"},"reference/classes/bsv.PrivateKey":{"id":"reference/classes/bsv.PrivateKey","title":"bsv.PrivateKey","description":"scrypt-ts / bsv / PrivateKey","sidebar":"tutorialSidebar"},"reference/classes/bsv.PublicKey":{"id":"reference/classes/bsv.PublicKey","title":"bsv.PublicKey","description":"scrypt-ts / bsv / PublicKey","sidebar":"tutorialSidebar"},"reference/classes/bsv.Script-1":{"id":"reference/classes/bsv.Script-1","title":"bsv.Script-1","description":"scrypt-ts / bsv / Script","sidebar":"tutorialSidebar"},"reference/classes/bsv.Script.Interpreter-1":{"id":"reference/classes/bsv.Script.Interpreter-1","title":"bsv.Script.Interpreter-1","description":"scrypt-ts / bsv / Script / Interpreter","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction-1":{"id":"reference/classes/bsv.Transaction-1","title":"bsv.Transaction-1","description":"scrypt-ts / bsv / Transaction","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.Input-1":{"id":"reference/classes/bsv.Transaction.Input-1","title":"bsv.Transaction.Input-1","description":"scrypt-ts / bsv / Transaction / Input","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.Input.PublicKeyHash":{"id":"reference/classes/bsv.Transaction.Input.PublicKeyHash","title":"bsv.Transaction.Input.PublicKeyHash","description":"scrypt-ts / bsv / Transaction / Input / PublicKeyHash","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.Output":{"id":"reference/classes/bsv.Transaction.Output","title":"bsv.Transaction.Output","description":"scrypt-ts / bsv / Transaction / Output","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.Signature":{"id":"reference/classes/bsv.Transaction.Signature","title":"bsv.Transaction.Signature","description":"scrypt-ts / bsv / Transaction / Signature","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.UnspentOutput":{"id":"reference/classes/bsv.Transaction.UnspentOutput","title":"bsv.Transaction.UnspentOutput","description":"scrypt-ts / bsv / Transaction / UnspentOutput","sidebar":"tutorialSidebar"},"reference/classes/bsv.Unit":{"id":"reference/classes/bsv.Unit","title":"bsv.Unit","description":"scrypt-ts / bsv / Unit","sidebar":"tutorialSidebar"},"reference/classes/BsvApi":{"id":"reference/classes/BsvApi","title":"BsvApi","description":"scrypt-ts / BsvApi","sidebar":"tutorialSidebar"},"reference/classes/Constants":{"id":"reference/classes/Constants","title":"Constants","description":"scrypt-ts / Constants","sidebar":"tutorialSidebar"},"reference/classes/ContractApi":{"id":"reference/classes/ContractApi","title":"ContractApi","description":"scrypt-ts / ContractApi","sidebar":"tutorialSidebar"},"reference/classes/DefaultProvider":{"id":"reference/classes/DefaultProvider","title":"DefaultProvider","description":"scrypt-ts / DefaultProvider","sidebar":"tutorialSidebar"},"reference/classes/DotwalletSigner":{"id":"reference/classes/DotwalletSigner","title":"DotwalletSigner","description":"scrypt-ts / DotwalletSigner","sidebar":"tutorialSidebar"},"reference/classes/DummyProvider":{"id":"reference/classes/DummyProvider","title":"DummyProvider","description":"scrypt-ts / DummyProvider","sidebar":"tutorialSidebar"},"reference/classes/FunctionCall":{"id":"reference/classes/FunctionCall","title":"FunctionCall","description":"scrypt-ts / FunctionCall","sidebar":"tutorialSidebar"},"reference/classes/GorillapoolProvider":{"id":"reference/classes/GorillapoolProvider","title":"GorillapoolProvider","description":"scrypt-ts / GorillapoolProvider","sidebar":"tutorialSidebar"},"reference/classes/HashedMap":{"id":"reference/classes/HashedMap","title":"HashedMap","description":"scrypt-ts / HashedMap","sidebar":"tutorialSidebar"},"reference/classes/HashedSet":{"id":"reference/classes/HashedSet","title":"HashedSet","description":"scrypt-ts / HashedSet","sidebar":"tutorialSidebar"},"reference/classes/OpCode":{"id":"reference/classes/OpCode","title":"OpCode","description":"scrypt-ts / OpCode","sidebar":"tutorialSidebar"},"reference/classes/Provider":{"id":"reference/classes/Provider","title":"Provider","description":"scrypt-ts / Provider","sidebar":"tutorialSidebar"},"reference/classes/ScryptProvider":{"id":"reference/classes/ScryptProvider","title":"ScryptProvider","description":"scrypt-ts / ScryptProvider","sidebar":"tutorialSidebar"},"reference/classes/SensibleProvider":{"id":"reference/classes/SensibleProvider","title":"SensibleProvider","description":"scrypt-ts / SensibleProvider","sidebar":"tutorialSidebar"},"reference/classes/SensiletSigner":{"id":"reference/classes/SensiletSigner","title":"SensiletSigner","description":"scrypt-ts / SensiletSigner","sidebar":"tutorialSidebar"},"reference/classes/SigHash":{"id":"reference/classes/SigHash","title":"SigHash","description":"scrypt-ts / SigHash","sidebar":"tutorialSidebar"},"reference/classes/Signer":{"id":"reference/classes/Signer","title":"Signer","description":"scrypt-ts / Signer","sidebar":"tutorialSidebar"},"reference/classes/SmartContract":{"id":"reference/classes/SmartContract","title":"SmartContract","description":"scrypt-ts / SmartContract","sidebar":"tutorialSidebar"},"reference/classes/SmartContractLib":{"id":"reference/classes/SmartContractLib","title":"SmartContractLib","description":"scrypt-ts / SmartContractLib","sidebar":"tutorialSidebar"},"reference/classes/TaalProvider":{"id":"reference/classes/TaalProvider","title":"TaalProvider","description":"scrypt-ts / TaalProvider","sidebar":"tutorialSidebar"},"reference/classes/TAALSigner":{"id":"reference/classes/TAALSigner","title":"TAALSigner","description":"scrypt-ts / TAALSigner","sidebar":"tutorialSidebar"},"reference/classes/TestWallet":{"id":"reference/classes/TestWallet","title":"TestWallet","description":"scrypt-ts / TestWallet","sidebar":"tutorialSidebar"},"reference/classes/Utils":{"id":"reference/classes/Utils","title":"Utils","description":"scrypt-ts / Utils","sidebar":"tutorialSidebar"},"reference/classes/VarIntReader":{"id":"reference/classes/VarIntReader","title":"VarIntReader","description":"scrypt-ts / VarIntReader","sidebar":"tutorialSidebar"},"reference/classes/VarIntWriter":{"id":"reference/classes/VarIntWriter","title":"VarIntWriter","description":"scrypt-ts / VarIntWriter","sidebar":"tutorialSidebar"},"reference/classes/WhatsonchainProvider":{"id":"reference/classes/WhatsonchainProvider","title":"WhatsonchainProvider","description":"scrypt-ts / WhatsonchainProvider","sidebar":"tutorialSidebar"},"reference/enums/ProviderEvent":{"id":"reference/enums/ProviderEvent","title":"ProviderEvent","description":"scrypt-ts / ProviderEvent","sidebar":"tutorialSidebar"},"reference/enums/SignatureHashType":{"id":"reference/enums/SignatureHashType","title":"SignatureHashType","description":"scrypt-ts / SignatureHashType","sidebar":"tutorialSidebar"},"reference/interfaces/Artifact":{"id":"reference/interfaces/Artifact","title":"Artifact","description":"scrypt-ts / Artifact","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.crypto.IOpts":{"id":"reference/interfaces/bsv.crypto.IOpts","title":"bsv.crypto.IOpts","description":"scrypt-ts / bsv / crypto / IOpts","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Networks.Network":{"id":"reference/interfaces/bsv.Networks.Network","title":"bsv.Networks.Network","description":"scrypt-ts / bsv / Networks / Network","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Script.Interpreter.InterpretState":{"id":"reference/interfaces/bsv.Script.Interpreter.InterpretState","title":"bsv.Script.Interpreter.InterpretState","description":"scrypt-ts / bsv / Script / Interpreter / InterpretState","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Script.IOpChunk":{"id":"reference/interfaces/bsv.Script.IOpChunk","title":"bsv.Script.IOpChunk","description":"scrypt-ts / bsv / Script / IOpChunk","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Transaction.IUnspentOutput":{"id":"reference/interfaces/bsv.Transaction.IUnspentOutput","title":"bsv.Transaction.IUnspentOutput","description":"scrypt-ts / bsv / Transaction / IUnspentOutput","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Util":{"id":"reference/interfaces/bsv.Util","title":"bsv.Util","description":"scrypt-ts / bsv / Util","sidebar":"tutorialSidebar"},"reference/interfaces/ContractCalledEvent":{"id":"reference/interfaces/ContractCalledEvent","title":"ContractCalledEvent","description":"scrypt-ts / ContractCalledEvent","sidebar":"tutorialSidebar"},"reference/interfaces/ContractTransaction":{"id":"reference/interfaces/ContractTransaction","title":"ContractTransaction","description":"scrypt-ts / ContractTransaction","sidebar":"tutorialSidebar"},"reference/interfaces/DefaultProviderOption":{"id":"reference/interfaces/DefaultProviderOption","title":"DefaultProviderOption","description":"scrypt-ts / DefaultProviderOption","sidebar":"tutorialSidebar"},"reference/interfaces/LogConfig":{"id":"reference/interfaces/LogConfig","title":"LogConfig","description":"scrypt-ts / LogConfig","sidebar":"tutorialSidebar"},"reference/interfaces/MethodCallOptions":{"id":"reference/interfaces/MethodCallOptions","title":"MethodCallOptions","description":"scrypt-ts / MethodCallOptions","sidebar":"tutorialSidebar"},"reference/interfaces/MethodCallTxBuilder":{"id":"reference/interfaces/MethodCallTxBuilder","title":"MethodCallTxBuilder","description":"scrypt-ts / MethodCallTxBuilder","sidebar":"tutorialSidebar"},"reference/interfaces/MultiContractCallOptions":{"id":"reference/interfaces/MultiContractCallOptions","title":"MultiContractCallOptions","description":"scrypt-ts / MultiContractCallOptions","sidebar":"tutorialSidebar"},"reference/interfaces/MultiContractTransaction":{"id":"reference/interfaces/MultiContractTransaction","title":"MultiContractTransaction","description":"scrypt-ts / MultiContractTransaction","sidebar":"tutorialSidebar"},"reference/interfaces/Outpoint":{"id":"reference/interfaces/Outpoint","title":"Outpoint","description":"scrypt-ts / Outpoint","sidebar":"tutorialSidebar"},"reference/interfaces/RequestConfig":{"id":"reference/interfaces/RequestConfig","title":"RequestConfig","description":"scrypt-ts / RequestConfig","sidebar":"tutorialSidebar"},"reference/interfaces/ScriptContext":{"id":"reference/interfaces/ScriptContext","title":"ScriptContext","description":"scrypt-ts / ScriptContext","sidebar":"tutorialSidebar"},"reference/interfaces/ScryptConfig":{"id":"reference/interfaces/ScryptConfig","title":"ScryptConfig","description":"scrypt-ts / ScryptConfig","sidebar":"tutorialSidebar"},"reference/interfaces/SignatureRequest":{"id":"reference/interfaces/SignatureRequest","title":"SignatureRequest","description":"scrypt-ts / SignatureRequest","sidebar":"tutorialSidebar"},"reference/interfaces/SignatureResponse":{"id":"reference/interfaces/SignatureResponse","title":"SignatureResponse","description":"scrypt-ts / SignatureResponse","sidebar":"tutorialSidebar"},"reference/interfaces/SignTransactionOptions":{"id":"reference/interfaces/SignTransactionOptions","title":"SignTransactionOptions","description":"scrypt-ts / SignTransactionOptions","sidebar":"tutorialSidebar"},"reference/interfaces/StatefulNext":{"id":"reference/interfaces/StatefulNext","title":"StatefulNext","description":"scrypt-ts / StatefulNext","sidebar":"tutorialSidebar"},"reference/interfaces/SubscribeOptions":{"id":"reference/interfaces/SubscribeOptions","title":"SubscribeOptions","description":"scrypt-ts / SubscribeOptions","sidebar":"tutorialSidebar"},"reference/interfaces/SubScription":{"id":"reference/interfaces/SubScription","title":"SubScription","description":"scrypt-ts / SubScription","sidebar":"tutorialSidebar"},"reference/interfaces/TransactionResponse":{"id":"reference/interfaces/TransactionResponse","title":"TransactionResponse","description":"scrypt-ts / TransactionResponse","sidebar":"tutorialSidebar"},"reference/interfaces/TxContext":{"id":"reference/interfaces/TxContext","title":"TxContext","description":"scrypt-ts / TxContext","sidebar":"tutorialSidebar"},"reference/interfaces/TxInputRef":{"id":"reference/interfaces/TxInputRef","title":"TxInputRef","description":"scrypt-ts / TxInputRef","sidebar":"tutorialSidebar"},"reference/interfaces/TxOutputRef":{"id":"reference/interfaces/TxOutputRef","title":"TxOutputRef","description":"scrypt-ts / TxOutputRef","sidebar":"tutorialSidebar"},"reference/interfaces/UtxoQueryOptions":{"id":"reference/interfaces/UtxoQueryOptions","title":"UtxoQueryOptions","description":"scrypt-ts / UtxoQueryOptions","sidebar":"tutorialSidebar"},"reference/interfaces/VerifyResult":{"id":"reference/interfaces/VerifyResult","title":"VerifyResult","description":"scrypt-ts / VerifyResult","sidebar":"tutorialSidebar"},"reference/modules/bsv":{"id":"reference/modules/bsv","title":"bsv","description":"scrypt-ts / bsv","sidebar":"tutorialSidebar"},"reference/modules/bsv.crypto":{"id":"reference/modules/bsv.crypto","title":"bsv.crypto","description":"scrypt-ts / bsv / crypto","sidebar":"tutorialSidebar"},"reference/modules/bsv.crypto.ECDSA":{"id":"reference/modules/bsv.crypto.ECDSA","title":"bsv.crypto.ECDSA","description":"scrypt-ts / bsv / crypto / ECDSA","sidebar":"tutorialSidebar"},"reference/modules/bsv.crypto.Hash":{"id":"reference/modules/bsv.crypto.Hash","title":"bsv.crypto.Hash","description":"scrypt-ts / bsv / crypto / Hash","sidebar":"tutorialSidebar"},"reference/modules/bsv.crypto.Random":{"id":"reference/modules/bsv.crypto.Random","title":"bsv.crypto.Random","description":"scrypt-ts / bsv / crypto / Random","sidebar":"tutorialSidebar"},"reference/modules/bsv.encoding":{"id":"reference/modules/bsv.encoding","title":"bsv.encoding","description":"scrypt-ts / bsv / encoding","sidebar":"tutorialSidebar"},"reference/modules/bsv.Networks":{"id":"reference/modules/bsv.Networks","title":"bsv.Networks","description":"scrypt-ts / bsv / Networks","sidebar":"tutorialSidebar"},"reference/modules/bsv.Script":{"id":"reference/modules/bsv.Script","title":"bsv.Script","description":"scrypt-ts / bsv / Script","sidebar":"tutorialSidebar"},"reference/modules/bsv.Script.Interpreter":{"id":"reference/modules/bsv.Script.Interpreter","title":"bsv.Script.Interpreter","description":"scrypt-ts / bsv / Script / Interpreter","sidebar":"tutorialSidebar"},"reference/modules/bsv.Transaction":{"id":"reference/modules/bsv.Transaction","title":"bsv.Transaction","description":"scrypt-ts / bsv / Transaction","sidebar":"tutorialSidebar"},"reference/modules/bsv.Transaction.Input":{"id":"reference/modules/bsv.Transaction.Input","title":"bsv.Transaction.Input","description":"scrypt-ts / bsv / Transaction / Input","sidebar":"tutorialSidebar"},"reference/modules/bsv.Transaction.Sighash":{"id":"reference/modules/bsv.Transaction.Sighash","title":"bsv.Transaction.Sighash","description":"scrypt-ts / bsv / Transaction / Sighash","sidebar":"tutorialSidebar"},"reference/README":{"id":"reference/README","title":"README","description":"scrypt-ts","sidebar":"tutorialSidebar"},"tokens/ft/existing":{"id":"tokens/ft/existing","title":"Transfer Existing FT to a Smart Contract","description":"Suppose you\'d like to unlock existing UTXOs that carry a FT to a smart contract.","sidebar":"tutorialSidebar"},"tokens/ft/ft":{"id":"tokens/ft/ft","title":"Fungible Tokens - FTs","description":"Just like NFTs, scrypt-ord also supports fungible tokens. Under the hood it utilizes the bsv-20 protocol.","sidebar":"tutorialSidebar"},"tokens/ft/multiple":{"id":"tokens/ft/multiple","title":"Multiple Inputs with Different Contracts","description":"Suppose we would like to unlock FTs within a single transaction that are located in different smart contracts. We can utilize the same technique demonstrated in the section for calling multiple contract instances.","sidebar":"tutorialSidebar"},"tokens/ft/woc-bsv20-plugin":{"id":"tokens/ft/woc-bsv20-plugin","title":"View BSV20 Token Transactions","description":"You can use WhatsOnChain to view a BSV20 token transaction, using our open source BSV20 plugin.","sidebar":"tutorialSidebar"},"tokens/nft/existing":{"id":"tokens/nft/existing","title":"Transfer Existing NFT to a Smart Contract","description":"Suppose you would like to transfer an existing NFT that was already inscribed in the past, which is typically locked using a P2PKH lock.","sidebar":"tutorialSidebar"},"tokens/nft/nft":{"id":"tokens/nft/nft","title":"Non Fungible Tokens - NFTs","description":"To create a smart contract that will carry an NFT, have your smart contract extend the OrdinalNFT class:","sidebar":"tutorialSidebar"},"tokens/tokens":{"id":"tokens/tokens","title":"The Official sCrypt 1Sat Ordinals SDK","description":"sCrypt offers its official 1Sat Ordinals SDK named scrypt-ord.","sidebar":"tutorialSidebar"},"tokens/tutorials/inscribe-image":{"id":"tokens/tutorials/inscribe-image","title":"Tutorial 1: Inscribe Image","description":"Overview","sidebar":"tutorialSidebar"},"tokens/tutorials/mint-bsv20-v1":{"id":"tokens/tutorials/mint-bsv20-v1","title":"Tutorial 3: Mint BSV20 V1 Token","description":"Overview","sidebar":"tutorialSidebar"},"tokens/tutorials/mint-bsv20-v2":{"id":"tokens/tutorials/mint-bsv20-v2","title":"Tutorial 2: Mint BSV20 V2 Token","description":"Overview","sidebar":"tutorialSidebar"},"tokens/tutorials/ordinal-lock":{"id":"tokens/tutorials/ordinal-lock","title":"Tutorial 4: Ordinal Lock","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/auction":{"id":"tutorials/auction","title":"Tutorial 2: Auction","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/escrow":{"id":"tutorials/escrow","title":"Tutorial 7: Escrow","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/hello-world":{"id":"tutorials/hello-world","title":"Tutorial 1: Hello World","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/oracle":{"id":"tutorials/oracle","title":"Tutorial 3: Oracle","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/tic-tac-toe":{"id":"tutorials/tic-tac-toe","title":"Tutorial 4: Tic Tac Toe","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/voting":{"id":"tutorials/voting","title":"Tutorial 6: Voting","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/zkp":{"id":"tutorials/zkp","title":"Tutorial 5: Zero Knowledge Proofs","description":"Overview","sidebar":"tutorialSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.d8dc81eb.js b/assets/js/935f2afb.d8dc81eb.js new file mode 100644 index 000000000..137bb829e --- /dev/null +++ b/assets/js/935f2afb.d8dc81eb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"tutorialSidebar":[{"type":"link","label":"Overview","href":"/","docId":"overview"},{"type":"link","label":"Installation","href":"/installation","docId":"installation"},{"type":"category","label":"Bitcoin Basics","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"The BSV submodule","href":"/bitcoin-basics/bsv","docId":"bitcoin-basics/bsv"}],"href":"/bitcoin-basics/"},{"type":"category","label":"How to Write a Contract","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ScriptContext","href":"/how-to-write-a-contract/scriptcontext","docId":"how-to-write-a-contract/scriptcontext"},{"type":"link","label":"Stateful Contracts","href":"/how-to-write-a-contract/stateful-contract","docId":"how-to-write-a-contract/stateful-contract"},{"type":"link","label":"Built-ins","href":"/how-to-write-a-contract/built-ins","docId":"how-to-write-a-contract/built-ins"}],"href":"/how-to-write-a-contract/"},{"type":"category","label":"How to Deploy & Call a Contract","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How to Customize a Contract Tx","href":"/how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx","docId":"how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx"},{"type":"link","label":"Deploy Using CLI","href":"/how-to-deploy-and-call-a-contract/deploy-cli","docId":"how-to-deploy-and-call-a-contract/deploy-cli"},{"type":"link","label":"Faucet","href":"/how-to-deploy-and-call-a-contract/faucet","docId":"how-to-deploy-and-call-a-contract/faucet"},{"type":"link","label":"Interact with a Deployed Contract","href":"/how-to-deploy-and-call-a-contract/call-deployed","docId":"how-to-deploy-and-call-a-contract/call-deployed"}],"href":"/how-to-deploy-and-call-a-contract/"},{"type":"link","label":"How to Test a Contract","href":"/how-to-test-a-contract","docId":"how-to-test-a-contract"},{"type":"link","label":"How to Debug a Contract","href":"/how-to-debug-a-contract","docId":"how-to-debug-a-contract"},{"type":"category","label":"How to Integrate With a Frontend","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How to integrate DotWallet","href":"/how-to-integrate-a-frontend/how-to-integrate-dotwallet","docId":"how-to-integrate-a-frontend/how-to-integrate-dotwallet"}],"href":"/how-to-integrate-a-frontend/"},{"type":"link","label":"How to Publish a Contract to NPM","href":"/how-to-publish-a-contract","docId":"how-to-publish-a-contract"},{"type":"link","label":"How to Verify a Contract","href":"/how-to-verify-a-contract","docId":"how-to-verify-a-contract"},{"type":"link","label":"sCrypt for Ethereum Developers","href":"/ethereum-devs","docId":"ethereum-devs"},{"type":"category","label":"Advanced","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"How to Integrate sCrypt Service","href":"/advanced/how-to-integrate-scrypt-service","docId":"advanced/how-to-integrate-scrypt-service"},{"type":"link","label":"Sighash Types","href":"/advanced/sighash-type","docId":"advanced/sighash-type"},{"type":"link","label":"How to Debug ScriptContext Failure","href":"/advanced/how-to-debug-scriptcontext","docId":"advanced/how-to-debug-scriptcontext"},{"type":"link","label":"Use Script inside sCrypt","href":"/advanced/inline-asm","docId":"advanced/inline-asm"},{"type":"link","label":"Use Code Separators","href":"/advanced/codeseparator","docId":"advanced/codeseparator"},{"type":"link","label":"How to Add a Provider","href":"/advanced/how-to-add-a-provider","docId":"advanced/how-to-add-a-provider"},{"type":"link","label":"How to Add a Signer","href":"/advanced/how-to-add-a-signer","docId":"advanced/how-to-add-a-signer"},{"type":"link","label":"Call Multiple Contracts in a Single Tx","href":"/advanced/how-to-call-multiple-contracts","docId":"advanced/how-to-call-multiple-contracts"},{"type":"link","label":"Time Lock","href":"/advanced/timeLock","docId":"advanced/timeLock"},{"type":"link","label":"How to Sign P2PKH Inputs Using the Signer Class","href":"/advanced/How to only sign p2pkh inputs","docId":"advanced/How to only sign p2pkh inputs"},{"type":"link","label":"How to Replay a Contract Instance to the Latest State","href":"/advanced/how-to-replay-instance","docId":"advanced/how-to-replay-instance"},{"type":"link","label":"How to Build an Oracle Service","href":"/advanced/how-to-build-an-oracle-service","docId":"advanced/how-to-build-an-oracle-service"}],"href":"/category/advanced"},{"type":"category","label":"Tokens","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Non Fungible Tokens - NFTs","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Transfer Existing NFT to a Smart Contract","href":"/tokens/nft/existing","docId":"tokens/nft/existing"}],"href":"/tokens/nft/"},{"type":"category","label":"Fungible Tokens - FTs","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Transfer Existing FT to a Smart Contract","href":"/tokens/ft/existing","docId":"tokens/ft/existing"},{"type":"link","label":"Multiple Inputs with Different Contracts","href":"/tokens/ft/multiple","docId":"tokens/ft/multiple"},{"type":"link","label":"View BSV20 Token Transactions","href":"/tokens/ft/woc-bsv20-plugin","docId":"tokens/ft/woc-bsv20-plugin"}],"href":"/tokens/ft/"},{"type":"category","label":"Tutorials","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Tutorial 1: Inscribe Image","href":"/tokens/tutorials/inscribe-image","docId":"tokens/tutorials/inscribe-image"},{"type":"link","label":"Tutorial 2: Mint BSV20 V2 Token","href":"/tokens/tutorials/mint-bsv20-v2","docId":"tokens/tutorials/mint-bsv20-v2"},{"type":"link","label":"Tutorial 3: Mint BSV20 V1 Token","href":"/tokens/tutorials/mint-bsv20-v1","docId":"tokens/tutorials/mint-bsv20-v1"},{"type":"link","label":"Tutorial 4: Ordinal Lock","href":"/tokens/tutorials/ordinal-lock","docId":"tokens/tutorials/ordinal-lock"}],"href":"/category/tutorials"}],"href":"/tokens/"},{"type":"category","label":"Tutorials","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Tutorial 1: Hello World","href":"/tutorials/hello-world","docId":"tutorials/hello-world"},{"type":"link","label":"Tutorial 2: Auction","href":"/tutorials/auction","docId":"tutorials/auction"},{"type":"link","label":"Tutorial 3: Oracle","href":"/tutorials/oracle","docId":"tutorials/oracle"},{"type":"link","label":"Tutorial 4: Tic Tac Toe","href":"/tutorials/tic-tac-toe","docId":"tutorials/tic-tac-toe"},{"type":"link","label":"Tutorial 5: Zero Knowledge Proofs","href":"/tutorials/zkp","docId":"tutorials/zkp"},{"type":"link","label":"Tutorial 6: Voting","href":"/tutorials/voting","docId":"tutorials/voting"},{"type":"link","label":"Tutorial 7: Escrow","href":"/tutorials/escrow","docId":"tutorials/escrow"},{"type":"link","label":"Tutorial 9: Ordinal Auction","href":"/tutorials/ordinal-auction","docId":"tutorials/ordinal-auction"}],"href":"/category/tutorials-1"},{"type":"link","label":"FAQ","href":"/faq","docId":"faq"},{"type":"category","label":"Reference","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"classes","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ActionError","href":"/reference/classes/ActionError","docId":"reference/classes/ActionError"},{"type":"link","label":"BsvApi","href":"/reference/classes/BsvApi","docId":"reference/classes/BsvApi"},{"type":"link","label":"Constants","href":"/reference/classes/Constants","docId":"reference/classes/Constants"},{"type":"link","label":"ContractApi","href":"/reference/classes/ContractApi","docId":"reference/classes/ContractApi"},{"type":"link","label":"DefaultProvider","href":"/reference/classes/DefaultProvider","docId":"reference/classes/DefaultProvider"},{"type":"link","label":"DotwalletSigner","href":"/reference/classes/DotwalletSigner","docId":"reference/classes/DotwalletSigner"},{"type":"link","label":"DummyProvider","href":"/reference/classes/DummyProvider","docId":"reference/classes/DummyProvider"},{"type":"link","label":"FunctionCall","href":"/reference/classes/FunctionCall","docId":"reference/classes/FunctionCall"},{"type":"link","label":"GorillapoolProvider","href":"/reference/classes/GorillapoolProvider","docId":"reference/classes/GorillapoolProvider"},{"type":"link","label":"HashedMap","href":"/reference/classes/HashedMap","docId":"reference/classes/HashedMap"},{"type":"link","label":"HashedSet","href":"/reference/classes/HashedSet","docId":"reference/classes/HashedSet"},{"type":"link","label":"OpCode","href":"/reference/classes/OpCode","docId":"reference/classes/OpCode"},{"type":"link","label":"Provider","href":"/reference/classes/Provider","docId":"reference/classes/Provider"},{"type":"link","label":"ScryptProvider","href":"/reference/classes/ScryptProvider","docId":"reference/classes/ScryptProvider"},{"type":"link","label":"SensibleProvider","href":"/reference/classes/SensibleProvider","docId":"reference/classes/SensibleProvider"},{"type":"link","label":"SensiletSigner","href":"/reference/classes/SensiletSigner","docId":"reference/classes/SensiletSigner"},{"type":"link","label":"SigHash","href":"/reference/classes/SigHash","docId":"reference/classes/SigHash"},{"type":"link","label":"Signer","href":"/reference/classes/Signer","docId":"reference/classes/Signer"},{"type":"link","label":"SmartContract","href":"/reference/classes/SmartContract","docId":"reference/classes/SmartContract"},{"type":"link","label":"SmartContractLib","href":"/reference/classes/SmartContractLib","docId":"reference/classes/SmartContractLib"},{"type":"link","label":"TAALSigner","href":"/reference/classes/TAALSigner","docId":"reference/classes/TAALSigner"},{"type":"link","label":"TaalProvider","href":"/reference/classes/TaalProvider","docId":"reference/classes/TaalProvider"},{"type":"link","label":"TestWallet","href":"/reference/classes/TestWallet","docId":"reference/classes/TestWallet"},{"type":"link","label":"Utils","href":"/reference/classes/Utils","docId":"reference/classes/Utils"},{"type":"link","label":"VarIntReader","href":"/reference/classes/VarIntReader","docId":"reference/classes/VarIntReader"},{"type":"link","label":"VarIntWriter","href":"/reference/classes/VarIntWriter","docId":"reference/classes/VarIntWriter"},{"type":"link","label":"WhatsonchainProvider","href":"/reference/classes/WhatsonchainProvider","docId":"reference/classes/WhatsonchainProvider"},{"type":"link","label":"bsv.Address","href":"/reference/classes/bsv.Address","docId":"reference/classes/bsv.Address"},{"type":"link","label":"bsv.Block","href":"/reference/classes/bsv.Block","docId":"reference/classes/bsv.Block"},{"type":"link","label":"bsv.BlockHeader","href":"/reference/classes/bsv.BlockHeader","docId":"reference/classes/bsv.BlockHeader"},{"type":"link","label":"bsv.ECIES","href":"/reference/classes/bsv.ECIES","docId":"reference/classes/bsv.ECIES"},{"type":"link","label":"bsv.HDPrivateKey","href":"/reference/classes/bsv.HDPrivateKey","docId":"reference/classes/bsv.HDPrivateKey"},{"type":"link","label":"bsv.HDPublicKey","href":"/reference/classes/bsv.HDPublicKey","docId":"reference/classes/bsv.HDPublicKey"},{"type":"link","label":"bsv.MerkleBlock","href":"/reference/classes/bsv.MerkleBlock","docId":"reference/classes/bsv.MerkleBlock"},{"type":"link","label":"bsv.Message","href":"/reference/classes/bsv.Message","docId":"reference/classes/bsv.Message"},{"type":"link","label":"bsv.Mnemonic","href":"/reference/classes/bsv.Mnemonic","docId":"reference/classes/bsv.Mnemonic"},{"type":"link","label":"bsv.Opcode","href":"/reference/classes/bsv.Opcode","docId":"reference/classes/bsv.Opcode"},{"type":"link","label":"bsv.PrivateKey","href":"/reference/classes/bsv.PrivateKey","docId":"reference/classes/bsv.PrivateKey"},{"type":"link","label":"bsv.PublicKey","href":"/reference/classes/bsv.PublicKey","docId":"reference/classes/bsv.PublicKey"},{"type":"link","label":"bsv.Script-1","href":"/reference/classes/bsv.Script-1","docId":"reference/classes/bsv.Script-1"},{"type":"link","label":"bsv.Script.Interpreter-1","href":"/reference/classes/bsv.Script.Interpreter-1","docId":"reference/classes/bsv.Script.Interpreter-1"},{"type":"link","label":"bsv.Transaction-1","href":"/reference/classes/bsv.Transaction-1","docId":"reference/classes/bsv.Transaction-1"},{"type":"link","label":"bsv.Transaction.Input-1","href":"/reference/classes/bsv.Transaction.Input-1","docId":"reference/classes/bsv.Transaction.Input-1"},{"type":"link","label":"bsv.Transaction.Input.PublicKeyHash","href":"/reference/classes/bsv.Transaction.Input.PublicKeyHash","docId":"reference/classes/bsv.Transaction.Input.PublicKeyHash"},{"type":"link","label":"bsv.Transaction.Output","href":"/reference/classes/bsv.Transaction.Output","docId":"reference/classes/bsv.Transaction.Output"},{"type":"link","label":"bsv.Transaction.Signature","href":"/reference/classes/bsv.Transaction.Signature","docId":"reference/classes/bsv.Transaction.Signature"},{"type":"link","label":"bsv.Transaction.UnspentOutput","href":"/reference/classes/bsv.Transaction.UnspentOutput","docId":"reference/classes/bsv.Transaction.UnspentOutput"},{"type":"link","label":"bsv.Unit","href":"/reference/classes/bsv.Unit","docId":"reference/classes/bsv.Unit"},{"type":"link","label":"bsv.crypto.BN","href":"/reference/classes/bsv.crypto.BN","docId":"reference/classes/bsv.crypto.BN"},{"type":"link","label":"bsv.crypto.Point","href":"/reference/classes/bsv.crypto.Point","docId":"reference/classes/bsv.crypto.Point"},{"type":"link","label":"bsv.crypto.Signature","href":"/reference/classes/bsv.crypto.Signature","docId":"reference/classes/bsv.crypto.Signature"},{"type":"link","label":"bsv.encoding.Base58","href":"/reference/classes/bsv.encoding.Base58","docId":"reference/classes/bsv.encoding.Base58"},{"type":"link","label":"bsv.encoding.Base58Check","href":"/reference/classes/bsv.encoding.Base58Check","docId":"reference/classes/bsv.encoding.Base58Check"},{"type":"link","label":"bsv.encoding.BufferReader","href":"/reference/classes/bsv.encoding.BufferReader","docId":"reference/classes/bsv.encoding.BufferReader"},{"type":"link","label":"bsv.encoding.BufferWriter","href":"/reference/classes/bsv.encoding.BufferWriter","docId":"reference/classes/bsv.encoding.BufferWriter"},{"type":"link","label":"bsv.encoding.Varint","href":"/reference/classes/bsv.encoding.Varint","docId":"reference/classes/bsv.encoding.Varint"}]},{"type":"category","label":"enums","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ProviderEvent","href":"/reference/enums/ProviderEvent","docId":"reference/enums/ProviderEvent"},{"type":"link","label":"SignatureHashType","href":"/reference/enums/SignatureHashType","docId":"reference/enums/SignatureHashType"}]},{"type":"category","label":"interfaces","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Artifact","href":"/reference/interfaces/Artifact","docId":"reference/interfaces/Artifact"},{"type":"link","label":"ContractCalledEvent","href":"/reference/interfaces/ContractCalledEvent","docId":"reference/interfaces/ContractCalledEvent"},{"type":"link","label":"ContractTransaction","href":"/reference/interfaces/ContractTransaction","docId":"reference/interfaces/ContractTransaction"},{"type":"link","label":"DefaultProviderOption","href":"/reference/interfaces/DefaultProviderOption","docId":"reference/interfaces/DefaultProviderOption"},{"type":"link","label":"LogConfig","href":"/reference/interfaces/LogConfig","docId":"reference/interfaces/LogConfig"},{"type":"link","label":"MethodCallOptions","href":"/reference/interfaces/MethodCallOptions","docId":"reference/interfaces/MethodCallOptions"},{"type":"link","label":"MethodCallTxBuilder","href":"/reference/interfaces/MethodCallTxBuilder","docId":"reference/interfaces/MethodCallTxBuilder"},{"type":"link","label":"MultiContractCallOptions","href":"/reference/interfaces/MultiContractCallOptions","docId":"reference/interfaces/MultiContractCallOptions"},{"type":"link","label":"MultiContractTransaction","href":"/reference/interfaces/MultiContractTransaction","docId":"reference/interfaces/MultiContractTransaction"},{"type":"link","label":"Outpoint","href":"/reference/interfaces/Outpoint","docId":"reference/interfaces/Outpoint"},{"type":"link","label":"RequestConfig","href":"/reference/interfaces/RequestConfig","docId":"reference/interfaces/RequestConfig"},{"type":"link","label":"ScriptContext","href":"/reference/interfaces/ScriptContext","docId":"reference/interfaces/ScriptContext"},{"type":"link","label":"ScryptConfig","href":"/reference/interfaces/ScryptConfig","docId":"reference/interfaces/ScryptConfig"},{"type":"link","label":"SignTransactionOptions","href":"/reference/interfaces/SignTransactionOptions","docId":"reference/interfaces/SignTransactionOptions"},{"type":"link","label":"SignatureRequest","href":"/reference/interfaces/SignatureRequest","docId":"reference/interfaces/SignatureRequest"},{"type":"link","label":"SignatureResponse","href":"/reference/interfaces/SignatureResponse","docId":"reference/interfaces/SignatureResponse"},{"type":"link","label":"StatefulNext","href":"/reference/interfaces/StatefulNext","docId":"reference/interfaces/StatefulNext"},{"type":"link","label":"SubScription","href":"/reference/interfaces/SubScription","docId":"reference/interfaces/SubScription"},{"type":"link","label":"SubscribeOptions","href":"/reference/interfaces/SubscribeOptions","docId":"reference/interfaces/SubscribeOptions"},{"type":"link","label":"TransactionResponse","href":"/reference/interfaces/TransactionResponse","docId":"reference/interfaces/TransactionResponse"},{"type":"link","label":"TxContext","href":"/reference/interfaces/TxContext","docId":"reference/interfaces/TxContext"},{"type":"link","label":"TxInputRef","href":"/reference/interfaces/TxInputRef","docId":"reference/interfaces/TxInputRef"},{"type":"link","label":"TxOutputRef","href":"/reference/interfaces/TxOutputRef","docId":"reference/interfaces/TxOutputRef"},{"type":"link","label":"UtxoQueryOptions","href":"/reference/interfaces/UtxoQueryOptions","docId":"reference/interfaces/UtxoQueryOptions"},{"type":"link","label":"VerifyResult","href":"/reference/interfaces/VerifyResult","docId":"reference/interfaces/VerifyResult"},{"type":"link","label":"bsv.Networks.Network","href":"/reference/interfaces/bsv.Networks.Network","docId":"reference/interfaces/bsv.Networks.Network"},{"type":"link","label":"bsv.Script.IOpChunk","href":"/reference/interfaces/bsv.Script.IOpChunk","docId":"reference/interfaces/bsv.Script.IOpChunk"},{"type":"link","label":"bsv.Script.Interpreter.InterpretState","href":"/reference/interfaces/bsv.Script.Interpreter.InterpretState","docId":"reference/interfaces/bsv.Script.Interpreter.InterpretState"},{"type":"link","label":"bsv.Transaction.IUnspentOutput","href":"/reference/interfaces/bsv.Transaction.IUnspentOutput","docId":"reference/interfaces/bsv.Transaction.IUnspentOutput"},{"type":"link","label":"bsv.Util","href":"/reference/interfaces/bsv.Util","docId":"reference/interfaces/bsv.Util"},{"type":"link","label":"bsv.crypto.IOpts","href":"/reference/interfaces/bsv.crypto.IOpts","docId":"reference/interfaces/bsv.crypto.IOpts"}]},{"type":"category","label":"modules","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"bsv.Networks","href":"/reference/modules/bsv.Networks","docId":"reference/modules/bsv.Networks"},{"type":"link","label":"bsv.Script.Interpreter","href":"/reference/modules/bsv.Script.Interpreter","docId":"reference/modules/bsv.Script.Interpreter"},{"type":"link","label":"bsv.Script","href":"/reference/modules/bsv.Script","docId":"reference/modules/bsv.Script"},{"type":"link","label":"bsv.Transaction.Input","href":"/reference/modules/bsv.Transaction.Input","docId":"reference/modules/bsv.Transaction.Input"},{"type":"link","label":"bsv.Transaction.Sighash","href":"/reference/modules/bsv.Transaction.Sighash","docId":"reference/modules/bsv.Transaction.Sighash"},{"type":"link","label":"bsv.Transaction","href":"/reference/modules/bsv.Transaction","docId":"reference/modules/bsv.Transaction"},{"type":"link","label":"bsv.crypto.ECDSA","href":"/reference/modules/bsv.crypto.ECDSA","docId":"reference/modules/bsv.crypto.ECDSA"},{"type":"link","label":"bsv.crypto.Hash","href":"/reference/modules/bsv.crypto.Hash","docId":"reference/modules/bsv.crypto.Hash"},{"type":"link","label":"bsv.crypto.Random","href":"/reference/modules/bsv.crypto.Random","docId":"reference/modules/bsv.crypto.Random"},{"type":"link","label":"bsv.crypto","href":"/reference/modules/bsv.crypto","docId":"reference/modules/bsv.crypto"},{"type":"link","label":"bsv.encoding","href":"/reference/modules/bsv.encoding","docId":"reference/modules/bsv.encoding"},{"type":"link","label":"bsv","href":"/reference/modules/bsv","docId":"reference/modules/bsv"}]}],"href":"/reference/"}]},"docs":{"advanced/codeseparator":{"id":"advanced/codeseparator","title":"Use Code Separators","description":"How Code Separators Work","sidebar":"tutorialSidebar"},"advanced/How to only sign p2pkh inputs":{"id":"advanced/How to only sign p2pkh inputs","title":"How to Sign P2PKH Inputs Using the Signer Class","description":"In certain scenarios, it is necessary to sign only P2PKH inputs when working with transactions in sCrypt. This documentation will guide you through the process of utilizing the Signer class to achieve this.","sidebar":"tutorialSidebar"},"advanced/how-to-add-a-provider":{"id":"advanced/how-to-add-a-provider","title":"How to Add a Provider","description":"In the contract testing section, we learned about the Provider class in sCrypt. This class serves as an abstraction of a Bitcoin node, allowing your application to communicate with the Bitcoin network.","sidebar":"tutorialSidebar"},"advanced/how-to-add-a-signer":{"id":"advanced/how-to-add-a-signer","title":"How to Add a Signer","description":"As described in this section, a signer is an abstraction of private keys, which can be used to sign messages and transactions. A simple signer would be a single private key, while a complex signer is a wallet.","sidebar":"tutorialSidebar"},"advanced/how-to-build-an-oracle-service":{"id":"advanced/how-to-build-an-oracle-service","title":"How to Build an Oracle Service","description":"As described in this tutorial, a blockchain oracle is a third-party service or agent that provides external data to a blockchain network. It is a bridge between the blockchain and the external world, enabling smart contracts to access, verify, and incorporate data from outside the blockchain. Specifically, the oracle service provides external data along with a Rabin signature of the data, and the smart contract uses this data and verifies the signature before using it.","sidebar":"tutorialSidebar"},"advanced/how-to-call-multiple-contracts":{"id":"advanced/how-to-call-multiple-contracts","title":"Call Multiple Contracts in a Single Tx","description":"Up to now, we have only shown how to call one smart contract in a transaction. That is, only one input of the tx spends a smart contract UTXO, and the other inputs, if any, spend Pay-to-Public-Key-Hash (P2PKH) UTXOs, which are generally NOT regarded as smart contracts.","sidebar":"tutorialSidebar"},"advanced/how-to-debug-scriptcontext":{"id":"advanced/how-to-debug-scriptcontext","title":"How to Debug ScriptContext Failure","description":"ScriptContext enables the logic of the contract to be executed correctly according to the agreement, and the state of the contract to be propagated correctly.","sidebar":"tutorialSidebar"},"advanced/how-to-integrate-scrypt-service":{"id":"advanced/how-to-integrate-scrypt-service","title":"How to Integrate sCrypt Service","description":"Before interacting with a sCrypt contract, we must create a contract instance representing the latest state of the contract on chain. Such an instance can be created by calling the fromTx method. However, this means your application needs to track and record all contract-related transactions, especially for a stateful contract.","sidebar":"tutorialSidebar"},"advanced/how-to-replay-instance":{"id":"advanced/how-to-replay-instance","title":"How to Replay a Contract Instance to the Latest State","description":"Using sCrypt Service and sCrypt client, we can effortlessly create a contract instance reflecting the latest state as follows:","sidebar":"tutorialSidebar"},"advanced/inline-asm":{"id":"advanced/inline-asm","title":"Use Script inside sCrypt","description":"Script is a low-level language and acts as assembly for the Bitcoin Virtual Machine. Usually, developers do not have to deal with it directly and can use high-level languages like sCrypt. However, there are cases where using script is desirable. For example, customized script is optimized and thus smaller and more efficient than Script generated by sCrypt. Or script is generated using external tools like Baguette and needs to be integrated into sCrypt.","sidebar":"tutorialSidebar"},"advanced/sighash-type":{"id":"advanced/sighash-type","title":"Sighash Types","description":"A signature hash (sighash) flag is used to indicate which part of the transaction is signed by the ECDSA signature. There are mainly two ways to use it in the context of Bitcoin smart contracts.","sidebar":"tutorialSidebar"},"advanced/timeLock":{"id":"advanced/timeLock","title":"Time Lock","description":"Overview","sidebar":"tutorialSidebar"},"bitcoin-basics/bitcoin-basics":{"id":"bitcoin-basics/bitcoin-basics","title":"Bitcoin Basics","description":"If you are new to Bitcoin development, we recommend exploring the resources listed in this section. While not an absolute prerequisite, going over these guides will provide a clearer understanding of key concepts and make it easier to begin developing sCrypt smart contracts.","sidebar":"tutorialSidebar"},"bitcoin-basics/bsv":{"id":"bitcoin-basics/bsv","title":"The BSV submodule","description":"sCrypt exports a submodule named bsv which is an interface that helps you manage low-level things for the Bitcoin blockchain, such as creating key pairs, building, signing and serializing Bitcoin transactions and more.","sidebar":"tutorialSidebar"},"ethereum-devs":{"id":"ethereum-devs","title":"sCrypt for Ethereum Developers","description":"Bitcoin and Ethereum are both layer-1 blockchains with fully programmable smart contracts.","sidebar":"tutorialSidebar"},"faq":{"id":"faq","title":"FAQ","description":"Smart contract call failure","sidebar":"tutorialSidebar"},"how-to-debug-a-contract":{"id":"how-to-debug-a-contract","title":"How to Debug a Contract","description":"Debugging an sCrypt contract is as easy as debugging TypeScript, since it is just TypeScript.","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/call-deployed":{"id":"how-to-deploy-and-call-a-contract/call-deployed","title":"Interact with a Deployed Contract","description":"Overview","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/deploy-cli":{"id":"how-to-deploy-and-call-a-contract/deploy-cli","title":"Deploy Using CLI","description":"The deploy command allows you to deploy an instance of a smart contract to the blockchain. You can simply run the following command in the root of an sCrypt project:","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/faucet":{"id":"how-to-deploy-and-call-a-contract/faucet","title":"Faucet","description":"It is highly recommended to test your contract on the testnet after passing local tests. It ensures that a contract can be successfully deployed and invoked as expected on the blockchain.","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx":{"id":"how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx","title":"How to Customize a Contract Tx","description":"Deployment Tx","sidebar":"tutorialSidebar"},"how-to-deploy-and-call-a-contract/how-to-deploy-and-call-a-contract":{"id":"how-to-deploy-and-call-a-contract/how-to-deploy-and-call-a-contract","title":"How to Deploy & Call a Contract","description":"Core Concepts","sidebar":"tutorialSidebar"},"how-to-integrate-a-frontend/how-to-integrate-a-frontend":{"id":"how-to-integrate-a-frontend/how-to-integrate-a-frontend","title":"How to Integrate With a Frontend","description":"This section will show how to integrate your smart contract to a frontend, so users can interact with it.","sidebar":"tutorialSidebar"},"how-to-integrate-a-frontend/how-to-integrate-dotwallet":{"id":"how-to-integrate-a-frontend/how-to-integrate-dotwallet","title":"How to integrate DotWallet","description":"DotWallet is a lightweight wallet designed to help users easily and securely manage their digital assets. We will show how to integrate it with sCrypt-powered apps.","sidebar":"tutorialSidebar"},"how-to-publish-a-contract":{"id":"how-to-publish-a-contract","title":"How to Publish a Contract to NPM","description":"What is a Smart Contract Library?","sidebar":"tutorialSidebar"},"how-to-test-a-contract":{"id":"how-to-test-a-contract","title":"How to Test a Contract","description":"Before using a smart contract in production, one should always test it carefully, especially because any bug in it may cause real economic losses.","sidebar":"tutorialSidebar"},"how-to-verify-a-contract":{"id":"how-to-verify-a-contract","title":"How to Verify a Contract","description":"You will learn how to verify smart contracts on WhatsOnChain (WoC), a blockchain explorer.","sidebar":"tutorialSidebar"},"how-to-write-a-contract/built-ins":{"id":"how-to-write-a-contract/built-ins","title":"Built-ins","description":"Global Functions","sidebar":"tutorialSidebar"},"how-to-write-a-contract/how-to-write-a-contract":{"id":"how-to-write-a-contract/how-to-write-a-contract","title":"How to Write a Contract","description":"A smart contract is a class that extends the SmartContract base class. A simple example is shown below.","sidebar":"tutorialSidebar"},"how-to-write-a-contract/scriptcontext":{"id":"how-to-write-a-contract/scriptcontext","title":"ScriptContext","description":"In the UTXO model, the context of validating a smart contract is the UTXO containing it and the transaction spending it, including its inputs and outputs. In the following example, when the second of input of transaction tx1 (2 inputs and 2 outputs) is spending the second output of tx0 (3 inputs and 3 outputs), the context for the smart contract in the latter output is roughly the UTXO and tx1 circled in red.","sidebar":"tutorialSidebar"},"how-to-write-a-contract/stateful-contract":{"id":"how-to-write-a-contract/stateful-contract","title":"Stateful Contracts","description":"Overview","sidebar":"tutorialSidebar"},"installation":{"id":"installation","title":"Installation","description":"Prerequisite","sidebar":"tutorialSidebar"},"overview":{"id":"overview","title":"Overview","description":"sCrypt is an embedded Domain Specific Language (eDSL) based on TypeScript for writing smart contracts on Bitcoin SV. Embedded means that it is a language inside another language. sCrypt is strictly a subset of TypeScript, so all sCrypt code is valid TypeScript, but not vice versa.","sidebar":"tutorialSidebar"},"reference/classes/ActionError":{"id":"reference/classes/ActionError","title":"ActionError","description":"scrypt-ts / ActionError","sidebar":"tutorialSidebar"},"reference/classes/bsv.Address":{"id":"reference/classes/bsv.Address","title":"bsv.Address","description":"scrypt-ts / bsv / Address","sidebar":"tutorialSidebar"},"reference/classes/bsv.Block":{"id":"reference/classes/bsv.Block","title":"bsv.Block","description":"scrypt-ts / bsv / Block","sidebar":"tutorialSidebar"},"reference/classes/bsv.BlockHeader":{"id":"reference/classes/bsv.BlockHeader","title":"bsv.BlockHeader","description":"scrypt-ts / bsv / BlockHeader","sidebar":"tutorialSidebar"},"reference/classes/bsv.crypto.BN":{"id":"reference/classes/bsv.crypto.BN","title":"bsv.crypto.BN","description":"scrypt-ts / bsv / crypto / BN","sidebar":"tutorialSidebar"},"reference/classes/bsv.crypto.Point":{"id":"reference/classes/bsv.crypto.Point","title":"bsv.crypto.Point","description":"scrypt-ts / bsv / crypto / Point","sidebar":"tutorialSidebar"},"reference/classes/bsv.crypto.Signature":{"id":"reference/classes/bsv.crypto.Signature","title":"bsv.crypto.Signature","description":"scrypt-ts / bsv / crypto / Signature","sidebar":"tutorialSidebar"},"reference/classes/bsv.ECIES":{"id":"reference/classes/bsv.ECIES","title":"bsv.ECIES","description":"scrypt-ts / bsv / ECIES","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.Base58":{"id":"reference/classes/bsv.encoding.Base58","title":"bsv.encoding.Base58","description":"scrypt-ts / bsv / encoding / Base58","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.Base58Check":{"id":"reference/classes/bsv.encoding.Base58Check","title":"bsv.encoding.Base58Check","description":"scrypt-ts / bsv / encoding / Base58Check","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.BufferReader":{"id":"reference/classes/bsv.encoding.BufferReader","title":"bsv.encoding.BufferReader","description":"scrypt-ts / bsv / encoding / BufferReader","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.BufferWriter":{"id":"reference/classes/bsv.encoding.BufferWriter","title":"bsv.encoding.BufferWriter","description":"scrypt-ts / bsv / encoding / BufferWriter","sidebar":"tutorialSidebar"},"reference/classes/bsv.encoding.Varint":{"id":"reference/classes/bsv.encoding.Varint","title":"bsv.encoding.Varint","description":"scrypt-ts / bsv / encoding / Varint","sidebar":"tutorialSidebar"},"reference/classes/bsv.HDPrivateKey":{"id":"reference/classes/bsv.HDPrivateKey","title":"bsv.HDPrivateKey","description":"scrypt-ts / bsv / HDPrivateKey","sidebar":"tutorialSidebar"},"reference/classes/bsv.HDPublicKey":{"id":"reference/classes/bsv.HDPublicKey","title":"bsv.HDPublicKey","description":"scrypt-ts / bsv / HDPublicKey","sidebar":"tutorialSidebar"},"reference/classes/bsv.MerkleBlock":{"id":"reference/classes/bsv.MerkleBlock","title":"bsv.MerkleBlock","description":"scrypt-ts / bsv / MerkleBlock","sidebar":"tutorialSidebar"},"reference/classes/bsv.Message":{"id":"reference/classes/bsv.Message","title":"bsv.Message","description":"scrypt-ts / bsv / Message","sidebar":"tutorialSidebar"},"reference/classes/bsv.Mnemonic":{"id":"reference/classes/bsv.Mnemonic","title":"bsv.Mnemonic","description":"scrypt-ts / bsv / Mnemonic","sidebar":"tutorialSidebar"},"reference/classes/bsv.Opcode":{"id":"reference/classes/bsv.Opcode","title":"bsv.Opcode","description":"scrypt-ts / bsv / Opcode","sidebar":"tutorialSidebar"},"reference/classes/bsv.PrivateKey":{"id":"reference/classes/bsv.PrivateKey","title":"bsv.PrivateKey","description":"scrypt-ts / bsv / PrivateKey","sidebar":"tutorialSidebar"},"reference/classes/bsv.PublicKey":{"id":"reference/classes/bsv.PublicKey","title":"bsv.PublicKey","description":"scrypt-ts / bsv / PublicKey","sidebar":"tutorialSidebar"},"reference/classes/bsv.Script-1":{"id":"reference/classes/bsv.Script-1","title":"bsv.Script-1","description":"scrypt-ts / bsv / Script","sidebar":"tutorialSidebar"},"reference/classes/bsv.Script.Interpreter-1":{"id":"reference/classes/bsv.Script.Interpreter-1","title":"bsv.Script.Interpreter-1","description":"scrypt-ts / bsv / Script / Interpreter","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction-1":{"id":"reference/classes/bsv.Transaction-1","title":"bsv.Transaction-1","description":"scrypt-ts / bsv / Transaction","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.Input-1":{"id":"reference/classes/bsv.Transaction.Input-1","title":"bsv.Transaction.Input-1","description":"scrypt-ts / bsv / Transaction / Input","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.Input.PublicKeyHash":{"id":"reference/classes/bsv.Transaction.Input.PublicKeyHash","title":"bsv.Transaction.Input.PublicKeyHash","description":"scrypt-ts / bsv / Transaction / Input / PublicKeyHash","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.Output":{"id":"reference/classes/bsv.Transaction.Output","title":"bsv.Transaction.Output","description":"scrypt-ts / bsv / Transaction / Output","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.Signature":{"id":"reference/classes/bsv.Transaction.Signature","title":"bsv.Transaction.Signature","description":"scrypt-ts / bsv / Transaction / Signature","sidebar":"tutorialSidebar"},"reference/classes/bsv.Transaction.UnspentOutput":{"id":"reference/classes/bsv.Transaction.UnspentOutput","title":"bsv.Transaction.UnspentOutput","description":"scrypt-ts / bsv / Transaction / UnspentOutput","sidebar":"tutorialSidebar"},"reference/classes/bsv.Unit":{"id":"reference/classes/bsv.Unit","title":"bsv.Unit","description":"scrypt-ts / bsv / Unit","sidebar":"tutorialSidebar"},"reference/classes/BsvApi":{"id":"reference/classes/BsvApi","title":"BsvApi","description":"scrypt-ts / BsvApi","sidebar":"tutorialSidebar"},"reference/classes/Constants":{"id":"reference/classes/Constants","title":"Constants","description":"scrypt-ts / Constants","sidebar":"tutorialSidebar"},"reference/classes/ContractApi":{"id":"reference/classes/ContractApi","title":"ContractApi","description":"scrypt-ts / ContractApi","sidebar":"tutorialSidebar"},"reference/classes/DefaultProvider":{"id":"reference/classes/DefaultProvider","title":"DefaultProvider","description":"scrypt-ts / DefaultProvider","sidebar":"tutorialSidebar"},"reference/classes/DotwalletSigner":{"id":"reference/classes/DotwalletSigner","title":"DotwalletSigner","description":"scrypt-ts / DotwalletSigner","sidebar":"tutorialSidebar"},"reference/classes/DummyProvider":{"id":"reference/classes/DummyProvider","title":"DummyProvider","description":"scrypt-ts / DummyProvider","sidebar":"tutorialSidebar"},"reference/classes/FunctionCall":{"id":"reference/classes/FunctionCall","title":"FunctionCall","description":"scrypt-ts / FunctionCall","sidebar":"tutorialSidebar"},"reference/classes/GorillapoolProvider":{"id":"reference/classes/GorillapoolProvider","title":"GorillapoolProvider","description":"scrypt-ts / GorillapoolProvider","sidebar":"tutorialSidebar"},"reference/classes/HashedMap":{"id":"reference/classes/HashedMap","title":"HashedMap","description":"scrypt-ts / HashedMap","sidebar":"tutorialSidebar"},"reference/classes/HashedSet":{"id":"reference/classes/HashedSet","title":"HashedSet","description":"scrypt-ts / HashedSet","sidebar":"tutorialSidebar"},"reference/classes/OpCode":{"id":"reference/classes/OpCode","title":"OpCode","description":"scrypt-ts / OpCode","sidebar":"tutorialSidebar"},"reference/classes/Provider":{"id":"reference/classes/Provider","title":"Provider","description":"scrypt-ts / Provider","sidebar":"tutorialSidebar"},"reference/classes/ScryptProvider":{"id":"reference/classes/ScryptProvider","title":"ScryptProvider","description":"scrypt-ts / ScryptProvider","sidebar":"tutorialSidebar"},"reference/classes/SensibleProvider":{"id":"reference/classes/SensibleProvider","title":"SensibleProvider","description":"scrypt-ts / SensibleProvider","sidebar":"tutorialSidebar"},"reference/classes/SensiletSigner":{"id":"reference/classes/SensiletSigner","title":"SensiletSigner","description":"scrypt-ts / SensiletSigner","sidebar":"tutorialSidebar"},"reference/classes/SigHash":{"id":"reference/classes/SigHash","title":"SigHash","description":"scrypt-ts / SigHash","sidebar":"tutorialSidebar"},"reference/classes/Signer":{"id":"reference/classes/Signer","title":"Signer","description":"scrypt-ts / Signer","sidebar":"tutorialSidebar"},"reference/classes/SmartContract":{"id":"reference/classes/SmartContract","title":"SmartContract","description":"scrypt-ts / SmartContract","sidebar":"tutorialSidebar"},"reference/classes/SmartContractLib":{"id":"reference/classes/SmartContractLib","title":"SmartContractLib","description":"scrypt-ts / SmartContractLib","sidebar":"tutorialSidebar"},"reference/classes/TaalProvider":{"id":"reference/classes/TaalProvider","title":"TaalProvider","description":"scrypt-ts / TaalProvider","sidebar":"tutorialSidebar"},"reference/classes/TAALSigner":{"id":"reference/classes/TAALSigner","title":"TAALSigner","description":"scrypt-ts / TAALSigner","sidebar":"tutorialSidebar"},"reference/classes/TestWallet":{"id":"reference/classes/TestWallet","title":"TestWallet","description":"scrypt-ts / TestWallet","sidebar":"tutorialSidebar"},"reference/classes/Utils":{"id":"reference/classes/Utils","title":"Utils","description":"scrypt-ts / Utils","sidebar":"tutorialSidebar"},"reference/classes/VarIntReader":{"id":"reference/classes/VarIntReader","title":"VarIntReader","description":"scrypt-ts / VarIntReader","sidebar":"tutorialSidebar"},"reference/classes/VarIntWriter":{"id":"reference/classes/VarIntWriter","title":"VarIntWriter","description":"scrypt-ts / VarIntWriter","sidebar":"tutorialSidebar"},"reference/classes/WhatsonchainProvider":{"id":"reference/classes/WhatsonchainProvider","title":"WhatsonchainProvider","description":"scrypt-ts / WhatsonchainProvider","sidebar":"tutorialSidebar"},"reference/enums/ProviderEvent":{"id":"reference/enums/ProviderEvent","title":"ProviderEvent","description":"scrypt-ts / ProviderEvent","sidebar":"tutorialSidebar"},"reference/enums/SignatureHashType":{"id":"reference/enums/SignatureHashType","title":"SignatureHashType","description":"scrypt-ts / SignatureHashType","sidebar":"tutorialSidebar"},"reference/interfaces/Artifact":{"id":"reference/interfaces/Artifact","title":"Artifact","description":"scrypt-ts / Artifact","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.crypto.IOpts":{"id":"reference/interfaces/bsv.crypto.IOpts","title":"bsv.crypto.IOpts","description":"scrypt-ts / bsv / crypto / IOpts","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Networks.Network":{"id":"reference/interfaces/bsv.Networks.Network","title":"bsv.Networks.Network","description":"scrypt-ts / bsv / Networks / Network","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Script.Interpreter.InterpretState":{"id":"reference/interfaces/bsv.Script.Interpreter.InterpretState","title":"bsv.Script.Interpreter.InterpretState","description":"scrypt-ts / bsv / Script / Interpreter / InterpretState","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Script.IOpChunk":{"id":"reference/interfaces/bsv.Script.IOpChunk","title":"bsv.Script.IOpChunk","description":"scrypt-ts / bsv / Script / IOpChunk","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Transaction.IUnspentOutput":{"id":"reference/interfaces/bsv.Transaction.IUnspentOutput","title":"bsv.Transaction.IUnspentOutput","description":"scrypt-ts / bsv / Transaction / IUnspentOutput","sidebar":"tutorialSidebar"},"reference/interfaces/bsv.Util":{"id":"reference/interfaces/bsv.Util","title":"bsv.Util","description":"scrypt-ts / bsv / Util","sidebar":"tutorialSidebar"},"reference/interfaces/ContractCalledEvent":{"id":"reference/interfaces/ContractCalledEvent","title":"ContractCalledEvent","description":"scrypt-ts / ContractCalledEvent","sidebar":"tutorialSidebar"},"reference/interfaces/ContractTransaction":{"id":"reference/interfaces/ContractTransaction","title":"ContractTransaction","description":"scrypt-ts / ContractTransaction","sidebar":"tutorialSidebar"},"reference/interfaces/DefaultProviderOption":{"id":"reference/interfaces/DefaultProviderOption","title":"DefaultProviderOption","description":"scrypt-ts / DefaultProviderOption","sidebar":"tutorialSidebar"},"reference/interfaces/LogConfig":{"id":"reference/interfaces/LogConfig","title":"LogConfig","description":"scrypt-ts / LogConfig","sidebar":"tutorialSidebar"},"reference/interfaces/MethodCallOptions":{"id":"reference/interfaces/MethodCallOptions","title":"MethodCallOptions","description":"scrypt-ts / MethodCallOptions","sidebar":"tutorialSidebar"},"reference/interfaces/MethodCallTxBuilder":{"id":"reference/interfaces/MethodCallTxBuilder","title":"MethodCallTxBuilder","description":"scrypt-ts / MethodCallTxBuilder","sidebar":"tutorialSidebar"},"reference/interfaces/MultiContractCallOptions":{"id":"reference/interfaces/MultiContractCallOptions","title":"MultiContractCallOptions","description":"scrypt-ts / MultiContractCallOptions","sidebar":"tutorialSidebar"},"reference/interfaces/MultiContractTransaction":{"id":"reference/interfaces/MultiContractTransaction","title":"MultiContractTransaction","description":"scrypt-ts / MultiContractTransaction","sidebar":"tutorialSidebar"},"reference/interfaces/Outpoint":{"id":"reference/interfaces/Outpoint","title":"Outpoint","description":"scrypt-ts / Outpoint","sidebar":"tutorialSidebar"},"reference/interfaces/RequestConfig":{"id":"reference/interfaces/RequestConfig","title":"RequestConfig","description":"scrypt-ts / RequestConfig","sidebar":"tutorialSidebar"},"reference/interfaces/ScriptContext":{"id":"reference/interfaces/ScriptContext","title":"ScriptContext","description":"scrypt-ts / ScriptContext","sidebar":"tutorialSidebar"},"reference/interfaces/ScryptConfig":{"id":"reference/interfaces/ScryptConfig","title":"ScryptConfig","description":"scrypt-ts / ScryptConfig","sidebar":"tutorialSidebar"},"reference/interfaces/SignatureRequest":{"id":"reference/interfaces/SignatureRequest","title":"SignatureRequest","description":"scrypt-ts / SignatureRequest","sidebar":"tutorialSidebar"},"reference/interfaces/SignatureResponse":{"id":"reference/interfaces/SignatureResponse","title":"SignatureResponse","description":"scrypt-ts / SignatureResponse","sidebar":"tutorialSidebar"},"reference/interfaces/SignTransactionOptions":{"id":"reference/interfaces/SignTransactionOptions","title":"SignTransactionOptions","description":"scrypt-ts / SignTransactionOptions","sidebar":"tutorialSidebar"},"reference/interfaces/StatefulNext":{"id":"reference/interfaces/StatefulNext","title":"StatefulNext","description":"scrypt-ts / StatefulNext","sidebar":"tutorialSidebar"},"reference/interfaces/SubscribeOptions":{"id":"reference/interfaces/SubscribeOptions","title":"SubscribeOptions","description":"scrypt-ts / SubscribeOptions","sidebar":"tutorialSidebar"},"reference/interfaces/SubScription":{"id":"reference/interfaces/SubScription","title":"SubScription","description":"scrypt-ts / SubScription","sidebar":"tutorialSidebar"},"reference/interfaces/TransactionResponse":{"id":"reference/interfaces/TransactionResponse","title":"TransactionResponse","description":"scrypt-ts / TransactionResponse","sidebar":"tutorialSidebar"},"reference/interfaces/TxContext":{"id":"reference/interfaces/TxContext","title":"TxContext","description":"scrypt-ts / TxContext","sidebar":"tutorialSidebar"},"reference/interfaces/TxInputRef":{"id":"reference/interfaces/TxInputRef","title":"TxInputRef","description":"scrypt-ts / TxInputRef","sidebar":"tutorialSidebar"},"reference/interfaces/TxOutputRef":{"id":"reference/interfaces/TxOutputRef","title":"TxOutputRef","description":"scrypt-ts / TxOutputRef","sidebar":"tutorialSidebar"},"reference/interfaces/UtxoQueryOptions":{"id":"reference/interfaces/UtxoQueryOptions","title":"UtxoQueryOptions","description":"scrypt-ts / UtxoQueryOptions","sidebar":"tutorialSidebar"},"reference/interfaces/VerifyResult":{"id":"reference/interfaces/VerifyResult","title":"VerifyResult","description":"scrypt-ts / VerifyResult","sidebar":"tutorialSidebar"},"reference/modules/bsv":{"id":"reference/modules/bsv","title":"bsv","description":"scrypt-ts / bsv","sidebar":"tutorialSidebar"},"reference/modules/bsv.crypto":{"id":"reference/modules/bsv.crypto","title":"bsv.crypto","description":"scrypt-ts / bsv / crypto","sidebar":"tutorialSidebar"},"reference/modules/bsv.crypto.ECDSA":{"id":"reference/modules/bsv.crypto.ECDSA","title":"bsv.crypto.ECDSA","description":"scrypt-ts / bsv / crypto / ECDSA","sidebar":"tutorialSidebar"},"reference/modules/bsv.crypto.Hash":{"id":"reference/modules/bsv.crypto.Hash","title":"bsv.crypto.Hash","description":"scrypt-ts / bsv / crypto / Hash","sidebar":"tutorialSidebar"},"reference/modules/bsv.crypto.Random":{"id":"reference/modules/bsv.crypto.Random","title":"bsv.crypto.Random","description":"scrypt-ts / bsv / crypto / Random","sidebar":"tutorialSidebar"},"reference/modules/bsv.encoding":{"id":"reference/modules/bsv.encoding","title":"bsv.encoding","description":"scrypt-ts / bsv / encoding","sidebar":"tutorialSidebar"},"reference/modules/bsv.Networks":{"id":"reference/modules/bsv.Networks","title":"bsv.Networks","description":"scrypt-ts / bsv / Networks","sidebar":"tutorialSidebar"},"reference/modules/bsv.Script":{"id":"reference/modules/bsv.Script","title":"bsv.Script","description":"scrypt-ts / bsv / Script","sidebar":"tutorialSidebar"},"reference/modules/bsv.Script.Interpreter":{"id":"reference/modules/bsv.Script.Interpreter","title":"bsv.Script.Interpreter","description":"scrypt-ts / bsv / Script / Interpreter","sidebar":"tutorialSidebar"},"reference/modules/bsv.Transaction":{"id":"reference/modules/bsv.Transaction","title":"bsv.Transaction","description":"scrypt-ts / bsv / Transaction","sidebar":"tutorialSidebar"},"reference/modules/bsv.Transaction.Input":{"id":"reference/modules/bsv.Transaction.Input","title":"bsv.Transaction.Input","description":"scrypt-ts / bsv / Transaction / Input","sidebar":"tutorialSidebar"},"reference/modules/bsv.Transaction.Sighash":{"id":"reference/modules/bsv.Transaction.Sighash","title":"bsv.Transaction.Sighash","description":"scrypt-ts / bsv / Transaction / Sighash","sidebar":"tutorialSidebar"},"reference/README":{"id":"reference/README","title":"README","description":"scrypt-ts","sidebar":"tutorialSidebar"},"tokens/ft/existing":{"id":"tokens/ft/existing","title":"Transfer Existing FT to a Smart Contract","description":"Suppose you\'d like to unlock existing UTXOs that carry a FT to a smart contract.","sidebar":"tutorialSidebar"},"tokens/ft/ft":{"id":"tokens/ft/ft","title":"Fungible Tokens - FTs","description":"Just like NFTs, scrypt-ord also supports fungible tokens. Under the hood it utilizes the bsv-20 protocol.","sidebar":"tutorialSidebar"},"tokens/ft/multiple":{"id":"tokens/ft/multiple","title":"Multiple Inputs with Different Contracts","description":"Suppose we would like to unlock FTs within a single transaction that are located in different smart contracts. We can utilize the same technique demonstrated in the section for calling multiple contract instances.","sidebar":"tutorialSidebar"},"tokens/ft/woc-bsv20-plugin":{"id":"tokens/ft/woc-bsv20-plugin","title":"View BSV20 Token Transactions","description":"You can use WhatsOnChain to view a BSV20 token transaction, using our open source BSV20 plugin.","sidebar":"tutorialSidebar"},"tokens/nft/existing":{"id":"tokens/nft/existing","title":"Transfer Existing NFT to a Smart Contract","description":"Suppose you would like to transfer an existing NFT that was already inscribed in the past, which is typically locked using a P2PKH lock.","sidebar":"tutorialSidebar"},"tokens/nft/nft":{"id":"tokens/nft/nft","title":"Non Fungible Tokens - NFTs","description":"To create a smart contract that will carry an NFT, have your smart contract extend the OrdinalNFT class:","sidebar":"tutorialSidebar"},"tokens/tokens":{"id":"tokens/tokens","title":"The Official sCrypt 1Sat Ordinals SDK","description":"sCrypt offers its official 1Sat Ordinals SDK named scrypt-ord.","sidebar":"tutorialSidebar"},"tokens/tutorials/inscribe-image":{"id":"tokens/tutorials/inscribe-image","title":"Tutorial 1: Inscribe Image","description":"Overview","sidebar":"tutorialSidebar"},"tokens/tutorials/mint-bsv20-v1":{"id":"tokens/tutorials/mint-bsv20-v1","title":"Tutorial 3: Mint BSV20 V1 Token","description":"Overview","sidebar":"tutorialSidebar"},"tokens/tutorials/mint-bsv20-v2":{"id":"tokens/tutorials/mint-bsv20-v2","title":"Tutorial 2: Mint BSV20 V2 Token","description":"Overview","sidebar":"tutorialSidebar"},"tokens/tutorials/ordinal-lock":{"id":"tokens/tutorials/ordinal-lock","title":"Tutorial 4: Ordinal Lock","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/auction":{"id":"tutorials/auction","title":"Tutorial 2: Auction","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/escrow":{"id":"tutorials/escrow","title":"Tutorial 7: Escrow","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/hello-world":{"id":"tutorials/hello-world","title":"Tutorial 1: Hello World","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/oracle":{"id":"tutorials/oracle","title":"Tutorial 3: Oracle","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/ordinal-auction":{"id":"tutorials/ordinal-auction","title":"Tutorial 9: Ordinal Auction","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/tic-tac-toe":{"id":"tutorials/tic-tac-toe","title":"Tutorial 4: Tic Tac Toe","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/voting":{"id":"tutorials/voting","title":"Tutorial 6: Voting","description":"Overview","sidebar":"tutorialSidebar"},"tutorials/zkp":{"id":"tutorials/zkp","title":"Tutorial 5: Zero Knowledge Proofs","description":"Overview","sidebar":"tutorialSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/b16c2f66.04979cd4.js b/assets/js/b16c2f66.04979cd4.js deleted file mode 100644 index e9f621f51..000000000 --- a/assets/js/b16c2f66.04979cd4.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[4346],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>h});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function r(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var c=a.createContext({}),s=function(e){var t=a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},p=function(e){var t=s(e.components);return a.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=s(n),h=i,u=d["".concat(c,".").concat(h)]||d[h]||m[h]||o;return n?a.createElement(u,r(r({ref:t},p),{},{components:n})):a.createElement(u,r({ref:t},p))}));function h(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,r=new Array(o);r[0]=d;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:i,r[1]=l;for(var s=2;s{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>m,frontMatter:()=>o,metadata:()=>l,toc:()=>s});var a=n(7462),i=(n(7294),n(3905));const o={sidebar_position:9},r="Time Lock",l={unversionedId:"advanced/timeLock",id:"advanced/timeLock",title:"Time Lock",description:"Overview",source:"@site/docs/advanced/timeLock.md",sourceDirName:"advanced",slug:"/advanced/timeLock",permalink:"/advanced/timeLock",draft:!1,tags:[],version:"current",sidebarPosition:9,frontMatter:{sidebar_position:9},sidebar:"tutorialSidebar",previous:{title:"Call Multiple Contracts in a Single Tx",permalink:"/advanced/how-to-call-multiple-contracts"},next:{title:"How to Replay a Contract Instance to the Latest State",permalink:"/advanced/how-to-replay-instance"}},c={},s=[{value:"Overview",id:"overview",level:2},{value:"What is a time lock?",id:"what-is-a-time-lock",level:3},{value:"Implementation",id:"implementation",level:3},{value:"Calling",id:"calling",level:4},{value:"How does it work?",id:"how-does-it-work",level:2}],p={toc:s};function m(e){let{components:t,...o}=e;return(0,i.kt)("wrapper",(0,a.Z)({},p,o,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"time-lock"},"Time Lock"),(0,i.kt)("h2",{id:"overview"},"Overview"),(0,i.kt)("p",null,"In this section, we will go over how to create a smart contract, which has a public method, that can only be unlocked once a certain point in time has passed."),(0,i.kt)("h3",{id:"what-is-a-time-lock"},"What is a time lock?"),(0,i.kt)("p",null,"In the context of smart contracts, a time-lock is a feature that restricts the spending of specific bitcoins until a specified future time or block height is reached. sCrypt offers capabilities to implement these types of time-locks in your smart contracts, providing a mechanism to ensure a transaction won't be included in a block before a certain point in time or block height is reached. In other words, the smart contract's method cannot be successfully invoked until that point in time has passed."),(0,i.kt)("p",null,"For instance, this mechanism could be used to add a withdrawal method to a smart contract. In the event of non-cooperation from other parties, an individual could retrieve their funds locked in the smart contract after some amount of time has passed. This approach is utilized in ",(0,i.kt)("a",{parentName:"p",href:"https://xiaohuiliu.medium.com/cross-chain-atomic-swaps-f13e874fcaa7"},"cross-chain atomic swaps"),", for example."),(0,i.kt)("p",null,(0,i.kt)("img",{src:n(4795).Z,width:"640",height:"320"}),"\n",(0,i.kt)("img",{src:n(3848).Z,width:"834",height:"418"}),"\n",(0,i.kt)("em",{parentName:"p"},"Image Credit: ",(0,i.kt)("a",{parentName:"em",href:"https://bcoin.io/guides/swaps.html"},"bcoin"))),(0,i.kt)("h3",{id:"implementation"},"Implementation"),(0,i.kt)("p",null,"In sCrypt, a time-lock can be enforced by constraining the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," values of the ",(0,i.kt)("a",{parentName:"p",href:"../how-to-write-a-contract/scriptcontext"},"script execution context"),". This context pertains to the execution of the transaction, which includes a call to the smart contract's public method. Thus, if the value is constrained \u2013 for example, the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," needs to be above the value ",(0,i.kt)("inlineCode",{parentName:"p"},"1690236000")," (a Unix timestamp) \u2013 then this transaction cannot be included into the blockchain until that point in time."),(0,i.kt)("p",null,"Note that the value of ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," can either be a Unix timestamp or a block height. For this value to be enforced, ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," also needs to be set to a value less than ",(0,i.kt)("inlineCode",{parentName:"p"},"0xffffffff"),"."),(0,i.kt)("p",null,"sCrypt offers a convenient built-in function ",(0,i.kt)("inlineCode",{parentName:"p"},"timeLock")," to enforce this constraint."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Time after which our public method can be called.\n@prop()\nreadonly matureTime: bigint // Can be a timestamp or block height.\n\n// ...\n\n@method()\npublic unlock() {\n // The following assertion ensures that the `unlock` method can\n // not be successfully invoked until `matureTime` has passed.\n assert(this.timeLock(this.matureTime), 'time lock not yet expired')\n}\n")),(0,i.kt)("p",null,"It is important to note that this mechanism can be employed solely to ensure that a method can be called ",(0,i.kt)("strong",{parentName:"p"},"after")," a specific point in time. In contrast, it cannot be employed to ensure that a method is called ",(0,i.kt)("strong",{parentName:"p"},"before")," a specific point in time. "),(0,i.kt)("h4",{id:"calling"},"Calling"),(0,i.kt)("p",null,"Upon a method call to the ",(0,i.kt)("inlineCode",{parentName:"p"},"unlock")," method defined above, we need to set the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," value of the transaction that will call the public method. We can do this by simply setting the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," paramater of ",(0,i.kt)("inlineCode",{parentName:"p"},"MethodCallOptions"),"."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"timeLock.methods.unlock(\n {\n lockTime: 1673523720\n } as MethodCallOptions\n)\n")),(0,i.kt)("p",null,"Internally this will also set the inputs ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," to a value lower than ",(0,i.kt)("inlineCode",{parentName:"p"},"0xffffffff"),". We can also set this value explicitly."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"timeLock.methods.unlock(\n {\n lockTime: 1673523720,\n sequence: 0\n } as MethodCallOptions\n)\n")),(0,i.kt)("p",null,"Lastly, if we are using a ",(0,i.kt)("a",{parentName:"p",href:"/how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx"},"custom transaction builder")," we need to set these values for the unsigned transaction that we are building there."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"instance.bindTxBuilder('unlock',\n async (\n current: TimeLock,\n options: MethodCallOptions\n ) => {\n\n // ...\n\n if (options.lockTime) {\n unsignedTx.setLockTime(options.lockTime)\n }\n unsignedTx.setInputSequence(0, 0)\n \n // ...\n }\n)\n")),(0,i.kt)("h2",{id:"how-does-it-work"},"How does it work?"),(0,i.kt)("p",null,"Under the hood, the ",(0,i.kt)("inlineCode",{parentName:"p"},"timeLock")," function asserts that the ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," value of our calling transaction is less than ",(0,i.kt)("inlineCode",{parentName:"p"},"UINT_MAX"),". This ensures that the Bitcoin network will enforce the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," value."),(0,i.kt)("p",null,"Next, it checks if our target time-lock value indicates a block height or a Unix timestamp. If it's using a block height, i.e. the time-lock value is less than 500,000,000, the method also ensures that the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," value of the calling transaction corresponds to a block height."),(0,i.kt)("p",null,"Lastly, the method verifies that the value of ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," is greater than or equal to the time-lock we have passed as an argument."),(0,i.kt)("p",null,"For more information on how the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," values work, please read the ",(0,i.kt)("a",{parentName:"p",href:"https://wiki.bitcoinsv.io/index.php/NLocktime_and_nSequence"},"BSV wiki page"),"."))}m.isMDXComponent=!0},4795:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/swap1-597f5664552aa55a2618d36c008f6e93.png"},3848:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/swap2-eb0d41670833d5dcc2aad196be3be44f.png"}}]); \ No newline at end of file diff --git a/assets/js/b16c2f66.a78054bc.js b/assets/js/b16c2f66.a78054bc.js new file mode 100644 index 000000000..bc1f3f596 --- /dev/null +++ b/assets/js/b16c2f66.a78054bc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[4346],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>h});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function r(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var c=a.createContext({}),s=function(e){var t=a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},p=function(e){var t=s(e.components);return a.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=s(n),h=i,u=d["".concat(c,".").concat(h)]||d[h]||m[h]||o;return n?a.createElement(u,r(r({ref:t},p),{},{components:n})):a.createElement(u,r({ref:t},p))}));function h(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,r=new Array(o);r[0]=d;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:i,r[1]=l;for(var s=2;s{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>m,frontMatter:()=>o,metadata:()=>l,toc:()=>s});var a=n(7462),i=(n(7294),n(3905));const o={sidebar_position:9},r="Time Lock",l={unversionedId:"advanced/timeLock",id:"advanced/timeLock",title:"Time Lock",description:"Overview",source:"@site/docs/advanced/timeLock.md",sourceDirName:"advanced",slug:"/advanced/timeLock",permalink:"/advanced/timeLock",draft:!1,tags:[],version:"current",sidebarPosition:9,frontMatter:{sidebar_position:9},sidebar:"tutorialSidebar",previous:{title:"Call Multiple Contracts in a Single Tx",permalink:"/advanced/how-to-call-multiple-contracts"},next:{title:"How to Sign P2PKH Inputs Using the Signer Class",permalink:"/advanced/How to only sign p2pkh inputs"}},c={},s=[{value:"Overview",id:"overview",level:2},{value:"What is a time lock?",id:"what-is-a-time-lock",level:3},{value:"Implementation",id:"implementation",level:3},{value:"Calling",id:"calling",level:4},{value:"How does it work?",id:"how-does-it-work",level:2}],p={toc:s};function m(e){let{components:t,...o}=e;return(0,i.kt)("wrapper",(0,a.Z)({},p,o,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"time-lock"},"Time Lock"),(0,i.kt)("h2",{id:"overview"},"Overview"),(0,i.kt)("p",null,"In this section, we will go over how to create a smart contract, which has a public method, that can only be unlocked once a certain point in time has passed."),(0,i.kt)("h3",{id:"what-is-a-time-lock"},"What is a time lock?"),(0,i.kt)("p",null,"In the context of smart contracts, a time-lock is a feature that restricts the spending of specific bitcoins until a specified future time or block height is reached. sCrypt offers capabilities to implement these types of time-locks in your smart contracts, providing a mechanism to ensure a transaction won't be included in a block before a certain point in time or block height is reached. In other words, the smart contract's method cannot be successfully invoked until that point in time has passed."),(0,i.kt)("p",null,"For instance, this mechanism could be used to add a withdrawal method to a smart contract. In the event of non-cooperation from other parties, an individual could retrieve their funds locked in the smart contract after some amount of time has passed. This approach is utilized in ",(0,i.kt)("a",{parentName:"p",href:"https://xiaohuiliu.medium.com/cross-chain-atomic-swaps-f13e874fcaa7"},"cross-chain atomic swaps"),", for example."),(0,i.kt)("p",null,(0,i.kt)("img",{src:n(4795).Z,width:"640",height:"320"}),"\n",(0,i.kt)("img",{src:n(3848).Z,width:"834",height:"418"}),"\n",(0,i.kt)("em",{parentName:"p"},"Image Credit: ",(0,i.kt)("a",{parentName:"em",href:"https://bcoin.io/guides/swaps.html"},"bcoin"))),(0,i.kt)("h3",{id:"implementation"},"Implementation"),(0,i.kt)("p",null,"In sCrypt, a time-lock can be enforced by constraining the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," values of the ",(0,i.kt)("a",{parentName:"p",href:"../how-to-write-a-contract/scriptcontext"},"script execution context"),". This context pertains to the execution of the transaction, which includes a call to the smart contract's public method. Thus, if the value is constrained \u2013 for example, the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," needs to be above the value ",(0,i.kt)("inlineCode",{parentName:"p"},"1690236000")," (a Unix timestamp) \u2013 then this transaction cannot be included into the blockchain until that point in time."),(0,i.kt)("p",null,"Note that the value of ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," can either be a Unix timestamp or a block height. For this value to be enforced, ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," also needs to be set to a value less than ",(0,i.kt)("inlineCode",{parentName:"p"},"0xffffffff"),"."),(0,i.kt)("p",null,"sCrypt offers a convenient built-in function ",(0,i.kt)("inlineCode",{parentName:"p"},"timeLock")," to enforce this constraint."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Time after which our public method can be called.\n@prop()\nreadonly matureTime: bigint // Can be a timestamp or block height.\n\n// ...\n\n@method()\npublic unlock() {\n // The following assertion ensures that the `unlock` method can\n // not be successfully invoked until `matureTime` has passed.\n assert(this.timeLock(this.matureTime), 'time lock not yet expired')\n}\n")),(0,i.kt)("p",null,"It is important to note that this mechanism can be employed solely to ensure that a method can be called ",(0,i.kt)("strong",{parentName:"p"},"after")," a specific point in time. In contrast, it cannot be employed to ensure that a method is called ",(0,i.kt)("strong",{parentName:"p"},"before")," a specific point in time. "),(0,i.kt)("h4",{id:"calling"},"Calling"),(0,i.kt)("p",null,"Upon a method call to the ",(0,i.kt)("inlineCode",{parentName:"p"},"unlock")," method defined above, we need to set the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," value of the transaction that will call the public method. We can do this by simply setting the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," paramater of ",(0,i.kt)("inlineCode",{parentName:"p"},"MethodCallOptions"),"."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"timeLock.methods.unlock(\n {\n lockTime: 1673523720\n } as MethodCallOptions\n)\n")),(0,i.kt)("p",null,"Internally this will also set the inputs ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," to a value lower than ",(0,i.kt)("inlineCode",{parentName:"p"},"0xffffffff"),". We can also set this value explicitly."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"timeLock.methods.unlock(\n {\n lockTime: 1673523720,\n sequence: 0\n } as MethodCallOptions\n)\n")),(0,i.kt)("p",null,"Lastly, if we are using a ",(0,i.kt)("a",{parentName:"p",href:"/how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx"},"custom transaction builder")," we need to set these values for the unsigned transaction that we are building there."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"instance.bindTxBuilder('unlock',\n async (\n current: TimeLock,\n options: MethodCallOptions\n ) => {\n\n // ...\n\n if (options.lockTime) {\n unsignedTx.setLockTime(options.lockTime)\n }\n unsignedTx.setInputSequence(0, 0)\n \n // ...\n }\n)\n")),(0,i.kt)("h2",{id:"how-does-it-work"},"How does it work?"),(0,i.kt)("p",null,"Under the hood, the ",(0,i.kt)("inlineCode",{parentName:"p"},"timeLock")," function asserts that the ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," value of our calling transaction is less than ",(0,i.kt)("inlineCode",{parentName:"p"},"UINT_MAX"),". This ensures that the Bitcoin network will enforce the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," value."),(0,i.kt)("p",null,"Next, it checks if our target time-lock value indicates a block height or a Unix timestamp. If it's using a block height, i.e. the time-lock value is less than 500,000,000, the method also ensures that the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," value of the calling transaction corresponds to a block height."),(0,i.kt)("p",null,"Lastly, the method verifies that the value of ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," is greater than or equal to the time-lock we have passed as an argument."),(0,i.kt)("p",null,"For more information on how the ",(0,i.kt)("inlineCode",{parentName:"p"},"locktime")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"sequence")," values work, please read the ",(0,i.kt)("a",{parentName:"p",href:"https://wiki.bitcoinsv.io/index.php/NLocktime_and_nSequence"},"BSV wiki page"),"."))}m.isMDXComponent=!0},4795:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/swap1-597f5664552aa55a2618d36c008f6e93.png"},3848:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/swap2-eb0d41670833d5dcc2aad196be3be44f.png"}}]); \ No newline at end of file diff --git a/assets/js/e37cbbfc.72e97d56.js b/assets/js/e37cbbfc.72e97d56.js deleted file mode 100644 index 620247423..000000000 --- a/assets/js/e37cbbfc.72e97d56.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[7139],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>p});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function s(e){for(var t=1;t=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var l=n.createContext({}),c=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):s(s({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,l=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),h=c(r),p=i,b=h["".concat(l,".").concat(p)]||h[p]||d[p]||a;return r?n.createElement(b,s(s({ref:t},u),{},{components:r})):n.createElement(b,s({ref:t},u))}));function p(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,s=new Array(a);s[0]=h;var o={};for(var l in t)hasOwnProperty.call(t,l)&&(o[l]=t[l]);o.originalType=e,o.mdxType="string"==typeof e?e:i,s[1]=o;for(var c=2;c{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var n=r(7462),i=(r(7294),r(3905));const a={sidebar_position:7},s="Tutorial 7: Escrow",o={unversionedId:"tutorials/escrow",id:"tutorials/escrow",title:"Tutorial 7: Escrow",description:"Overview",source:"@site/docs/tutorials/escrow.md",sourceDirName:"tutorials",slug:"/tutorials/escrow",permalink:"/tutorials/escrow",draft:!1,tags:[],version:"current",sidebarPosition:7,frontMatter:{sidebar_position:7},sidebar:"tutorialSidebar",previous:{title:"Tutorial 6: Voting",permalink:"/tutorials/voting"},next:{title:"FAQ",permalink:"/faq"}},l={},c=[{value:"Overview",id:"overview",level:2},{value:"What is an escrow smart contract?",id:"what-is-an-escrow-smart-contract",level:3},{value:"Our implementation",id:"our-implementation",level:3},{value:"Contract properties",id:"contract-properties",level:2},{value:"Public method - confirmPayment",id:"public-method---confirmpayment",level:2},{value:"Public method - refund",id:"public-method---refund",level:2},{value:"Public method - refundDeadline",id:"public-method---refunddeadline",level:2},{value:"Conclusion",id:"conclusion",level:2}],u={toc:c};function d(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"tutorial-7-escrow"},"Tutorial 7: Escrow"),(0,i.kt)("h2",{id:"overview"},"Overview"),(0,i.kt)("p",null,"In this tutorial, we will go over how to create and escrow smart contract with some advanced features, such as a requirement for multiple arbiters and a deadline, after which the buyer can get a refund."),(0,i.kt)("h3",{id:"what-is-an-escrow-smart-contract"},"What is an escrow smart contract?"),(0,i.kt)("p",null,"An escrow smart contract is a type of digital agreement that Bitcoin to facilitate transactions between parties in a secure, trustless manner. "),(0,i.kt)("p",null,"In traditional escrow services, a trusted third party holds assets\u2014like money, property, or goods\u2014on behalf of the transacting parties. The assets are released only when specific conditions are met."),(0,i.kt)("p",null,'In the case of an escrow smart contract, the "third party" is the smart contract itself, programmed on the blockchain. The contract is written with the conditions of the transaction, and if they are met, the contract can be unlocked and the recipient(s) get payed.'),(0,i.kt)("h3",{id:"our-implementation"},"Our implementation"),(0,i.kt)("p",null,"We will implement a specific type of escrow, called a multi-sig escrow. The participants of this contract are a buyer (Alice), a seller (Bob) and one or more arbiters."),(0,i.kt)("p",null,"Suppose Alice want's to buy a specific item from Bob. They don't trust each other, so they decide to use an escrow smart contract. They pick one or more arbiters, which they both trust. The job of the chosen arbiters is to verify, that the item really gets delivered in the right condition. If the conditions are met, the contract will pay the seller, Bob. In the opposite case, Alice gets a refund. Additionally, Alice is also eligible for a refund after a set period of time in the case the arbiters are not responsive."),(0,i.kt)("h2",{id:"contract-properties"},"Contract properties"),(0,i.kt)("p",null,"Let's declare the properties of our smart contract:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Number of arbiters chosen.\nstatic readonly N_ARBITERS = 3\n\n// Buyer (Alice) address.\n@prop()\nreadonly buyerAddr: Addr\n\n// Seller (Bob) address.\n@prop()\nreadonly sellerAddr: Addr\n\n// Arbiter public keys.\n@prop()\nreadonly arbiters: FixedArray\n\n// Contract deadline nLocktime value.\n// Either timestamp or block height.\n@prop()\nreadonly deadline: bigint\n")),(0,i.kt)("h2",{id:"public-method---confirmpayment"},"Public method - ",(0,i.kt)("inlineCode",{parentName:"h2"},"confirmPayment")),(0,i.kt)("p",null,"The first method of our contract will be ",(0,i.kt)("inlineCode",{parentName:"p"},"confirmPayment"),". This public method will be called if the item was successfully delivered in the right condition."),(0,i.kt)("p",null,"The method takes as inputs the buyers signature, along with her public key and the signatures of the arbiters."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Buyer and arbiters confirm, that the item was delivered.\n// Seller gets paid.\n@method(SigHash.ANYONECANPAY_SINGLE)\npublic confirmPayment(\n buyerSig: Sig,\n buyerPubKey: PubKey,\n arbiterSigs: FixedArray\n) {\n // Validate buyer sig.\n assert(\n pubKey2Addr(buyerPubKey) == this.buyerAddr,\n 'invalid public key for buyer'\n )\n assert(\n this.checkSig(buyerSig, buyerPubKey),\n 'buyer signature check failed'\n )\n\n // Validate arbiter sigs.\n assert(\n this.checkMultiSig(arbiterSigs, this.arbiters),\n 'arbiters checkMultiSig failed'\n )\n\n // Ensure seller gets payed.\n const amount = this.ctx.utxo.value\n const out = Utils.buildPublicKeyHashOutput(this.sellerAddr, amount)\n assert(hash256(out) == this.ctx.hashOutputs, 'hashOutputs mismatch')\n}\n")),(0,i.kt)("p",null,"The method validates all signatures are correct and ensures the ",(0,i.kt)("strong",{parentName:"p"},"seller")," receives the funds."),(0,i.kt)("h2",{id:"public-method---refund"},"Public method - ",(0,i.kt)("inlineCode",{parentName:"h2"},"refund")),(0,i.kt)("p",null,"Next, we implement the public method ",(0,i.kt)("inlineCode",{parentName:"p"},"refund"),". If the delivery wasn't successful or there is something wrong with the item and needs to be sent back, the buyer is eligible for a refund."),(0,i.kt)("p",null,"The method again takes as inputs the buyers signature, along with her public key and the signatures of the arbiters."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Regular refund. Needs arbiters agreement.\n@method()\npublic refund(\n buyerSig: Sig,\n buyerPubKey: PubKey,\n arbiterSigs: FixedArray\n) {\n // Validate buyer sig.\n assert(\n pubKey2Addr(buyerPubKey) == this.buyerAddr,\n 'invalid public key for buyer'\n )\n assert(\n this.checkSig(buyerSig, buyerPubKey),\n 'buyer signature check failed'\n )\n\n // Validate arbiter sigs.\n assert(\n this.checkMultiSig(arbiterSigs, this.arbiters),\n 'arbiters checkMultiSig failed'\n )\n\n // Ensure buyer gets refund.\n const amount = this.ctx.utxo.value\n const out = Utils.buildPublicKeyHashOutput(this.buyerAddr, amount)\n assert(hash256(out) == this.ctx.hashOutputs, 'hashOutputs mismatch')\n}\n")),(0,i.kt)("p",null,"The method validates all signatures are correct and ensures the ",(0,i.kt)("strong",{parentName:"p"},"buyer")," receives the refund."),(0,i.kt)("h2",{id:"public-method---refunddeadline"},"Public method - ",(0,i.kt)("inlineCode",{parentName:"h2"},"refundDeadline")),(0,i.kt)("p",null,"Lastly, we implement the ",(0,i.kt)("inlineCode",{parentName:"p"},"refundDeadline")," method. This method can be called, after the specified contract deadline has been reached. After the deadline, the buyer can receive the refund, even without the arbiters agreement."),(0,i.kt)("p",null,"The method takes as inputs in the buyers signature, along with her public key."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Deadline for delivery. If reached, the buyer gets refunded.\n@method()\npublic refundDeadline(buyerSig: Sig, buyerPubKey: PubKey) {\n assert(\n pubKey2Addr(buyerPubKey) == this.buyerAddr,\n 'invalid public key for buyer'\n )\n assert(\n this.checkSig(buyerSig, buyerPubKey),\n 'buyer signature check failed'\n )\n\n // Require nLocktime enabled https://wiki.bitcoinsv.io/index.php/NLocktime_and_nSequence\n assert(\n this.ctx.sequence < UINT_MAX,\n 'require nLocktime enabled'\n )\n\n // Check if using block height.\n if (this.deadline < LOCKTIME_BLOCK_HEIGHT_MARKER) {\n // Enforce nLocktime field to also use block height.\n assert(\n this.ctx.locktime < LOCKTIME_BLOCK_HEIGHT_MARKER\n )\n }\n assert(this.ctx.locktime >= this.deadline, 'deadline not yet reached')\n\n // Ensure buyer gets refund.\n const amount = this.ctx.utxo.value\n const out = Utils.buildPublicKeyHashOutput(this.buyerAddr, amount)\n assert(hash256(out) == this.ctx.hashOutputs, 'hashOutputs mismatch')\n}\n")),(0,i.kt)("p",null,"The method checks the buyers signature validity. It also checks the transaction nLocktime value, to ensure it can be accepted by miners only after the deadline."),(0,i.kt)("h2",{id:"conclusion"},"Conclusion"),(0,i.kt)("p",null,"Congratulations! You have completed the escrow tutorial!"),(0,i.kt)("p",null,"The full code can be found in our ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/sCrypt-Inc/boilerplate/blob/master/src/contracts/multisigEscrow.ts"},"boilerplate repository"),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e37cbbfc.98321c60.js b/assets/js/e37cbbfc.98321c60.js new file mode 100644 index 000000000..bcd547524 --- /dev/null +++ b/assets/js/e37cbbfc.98321c60.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[7139],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>p});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var l=n.createContext({}),c=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),h=c(r),p=i,b=h["".concat(l,".").concat(p)]||h[p]||d[p]||a;return r?n.createElement(b,o(o({ref:t},u),{},{components:r})):n.createElement(b,o({ref:t},u))}));function p(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,o=new Array(a);o[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,o[1]=s;for(var c=2;c{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>c});var n=r(7462),i=(r(7294),r(3905));const a={sidebar_position:7},o="Tutorial 7: Escrow",s={unversionedId:"tutorials/escrow",id:"tutorials/escrow",title:"Tutorial 7: Escrow",description:"Overview",source:"@site/docs/tutorials/escrow.md",sourceDirName:"tutorials",slug:"/tutorials/escrow",permalink:"/tutorials/escrow",draft:!1,tags:[],version:"current",sidebarPosition:7,frontMatter:{sidebar_position:7},sidebar:"tutorialSidebar",previous:{title:"Tutorial 6: Voting",permalink:"/tutorials/voting"},next:{title:"Tutorial 9: Ordinal Auction",permalink:"/tutorials/ordinal-auction"}},l={},c=[{value:"Overview",id:"overview",level:2},{value:"What is an escrow smart contract?",id:"what-is-an-escrow-smart-contract",level:3},{value:"Our implementation",id:"our-implementation",level:3},{value:"Contract properties",id:"contract-properties",level:2},{value:"Public method - confirmPayment",id:"public-method---confirmpayment",level:2},{value:"Public method - refund",id:"public-method---refund",level:2},{value:"Public method - refundDeadline",id:"public-method---refunddeadline",level:2},{value:"Conclusion",id:"conclusion",level:2}],u={toc:c};function d(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"tutorial-7-escrow"},"Tutorial 7: Escrow"),(0,i.kt)("h2",{id:"overview"},"Overview"),(0,i.kt)("p",null,"In this tutorial, we will go over how to create and escrow smart contract with some advanced features, such as a requirement for multiple arbiters and a deadline, after which the buyer can get a refund."),(0,i.kt)("h3",{id:"what-is-an-escrow-smart-contract"},"What is an escrow smart contract?"),(0,i.kt)("p",null,"An escrow smart contract is a type of digital agreement that Bitcoin to facilitate transactions between parties in a secure, trustless manner. "),(0,i.kt)("p",null,"In traditional escrow services, a trusted third party holds assets\u2014like money, property, or goods\u2014on behalf of the transacting parties. The assets are released only when specific conditions are met."),(0,i.kt)("p",null,'In the case of an escrow smart contract, the "third party" is the smart contract itself, programmed on the blockchain. The contract is written with the conditions of the transaction, and if they are met, the contract can be unlocked and the recipient(s) get payed.'),(0,i.kt)("h3",{id:"our-implementation"},"Our implementation"),(0,i.kt)("p",null,"We will implement a specific type of escrow, called a multi-sig escrow. The participants of this contract are a buyer (Alice), a seller (Bob) and one or more arbiters."),(0,i.kt)("p",null,"Suppose Alice want's to buy a specific item from Bob. They don't trust each other, so they decide to use an escrow smart contract. They pick one or more arbiters, which they both trust. The job of the chosen arbiters is to verify, that the item really gets delivered in the right condition. If the conditions are met, the contract will pay the seller, Bob. In the opposite case, Alice gets a refund. Additionally, Alice is also eligible for a refund after a set period of time in the case the arbiters are not responsive."),(0,i.kt)("h2",{id:"contract-properties"},"Contract properties"),(0,i.kt)("p",null,"Let's declare the properties of our smart contract:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Number of arbiters chosen.\nstatic readonly N_ARBITERS = 3\n\n// Buyer (Alice) address.\n@prop()\nreadonly buyerAddr: Addr\n\n// Seller (Bob) address.\n@prop()\nreadonly sellerAddr: Addr\n\n// Arbiter public keys.\n@prop()\nreadonly arbiters: FixedArray\n\n// Contract deadline nLocktime value.\n// Either timestamp or block height.\n@prop()\nreadonly deadline: bigint\n")),(0,i.kt)("h2",{id:"public-method---confirmpayment"},"Public method - ",(0,i.kt)("inlineCode",{parentName:"h2"},"confirmPayment")),(0,i.kt)("p",null,"The first method of our contract will be ",(0,i.kt)("inlineCode",{parentName:"p"},"confirmPayment"),". This public method will be called if the item was successfully delivered in the right condition."),(0,i.kt)("p",null,"The method takes as inputs the buyers signature, along with her public key and the signatures of the arbiters."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Buyer and arbiters confirm, that the item was delivered.\n// Seller gets paid.\n@method(SigHash.ANYONECANPAY_SINGLE)\npublic confirmPayment(\n buyerSig: Sig,\n buyerPubKey: PubKey,\n arbiterSigs: FixedArray\n) {\n // Validate buyer sig.\n assert(\n pubKey2Addr(buyerPubKey) == this.buyerAddr,\n 'invalid public key for buyer'\n )\n assert(\n this.checkSig(buyerSig, buyerPubKey),\n 'buyer signature check failed'\n )\n\n // Validate arbiter sigs.\n assert(\n this.checkMultiSig(arbiterSigs, this.arbiters),\n 'arbiters checkMultiSig failed'\n )\n\n // Ensure seller gets payed.\n const amount = this.ctx.utxo.value\n const out = Utils.buildPublicKeyHashOutput(this.sellerAddr, amount)\n assert(hash256(out) == this.ctx.hashOutputs, 'hashOutputs mismatch')\n}\n")),(0,i.kt)("p",null,"The method validates all signatures are correct and ensures the ",(0,i.kt)("strong",{parentName:"p"},"seller")," receives the funds."),(0,i.kt)("h2",{id:"public-method---refund"},"Public method - ",(0,i.kt)("inlineCode",{parentName:"h2"},"refund")),(0,i.kt)("p",null,"Next, we implement the public method ",(0,i.kt)("inlineCode",{parentName:"p"},"refund"),". If the delivery wasn't successful or there is something wrong with the item and needs to be sent back, the buyer is eligible for a refund."),(0,i.kt)("p",null,"The method again takes as inputs the buyers signature, along with her public key and the signatures of the arbiters."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Regular refund. Needs arbiters agreement.\n@method()\npublic refund(\n buyerSig: Sig,\n buyerPubKey: PubKey,\n arbiterSigs: FixedArray\n) {\n // Validate buyer sig.\n assert(\n pubKey2Addr(buyerPubKey) == this.buyerAddr,\n 'invalid public key for buyer'\n )\n assert(\n this.checkSig(buyerSig, buyerPubKey),\n 'buyer signature check failed'\n )\n\n // Validate arbiter sigs.\n assert(\n this.checkMultiSig(arbiterSigs, this.arbiters),\n 'arbiters checkMultiSig failed'\n )\n\n // Ensure buyer gets refund.\n const amount = this.ctx.utxo.value\n const out = Utils.buildPublicKeyHashOutput(this.buyerAddr, amount)\n assert(hash256(out) == this.ctx.hashOutputs, 'hashOutputs mismatch')\n}\n")),(0,i.kt)("p",null,"The method validates all signatures are correct and ensures the ",(0,i.kt)("strong",{parentName:"p"},"buyer")," receives the refund."),(0,i.kt)("h2",{id:"public-method---refunddeadline"},"Public method - ",(0,i.kt)("inlineCode",{parentName:"h2"},"refundDeadline")),(0,i.kt)("p",null,"Lastly, we implement the ",(0,i.kt)("inlineCode",{parentName:"p"},"refundDeadline")," method. This method can be called, after the specified contract deadline has been reached. After the deadline, the buyer can receive the refund, even without the arbiters agreement."),(0,i.kt)("p",null,"The method takes as inputs in the buyers signature, along with her public key."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-ts"},"// Deadline for delivery. If reached, the buyer gets refunded.\n@method()\npublic refundDeadline(buyerSig: Sig, buyerPubKey: PubKey) {\n assert(\n pubKey2Addr(buyerPubKey) == this.buyerAddr,\n 'invalid public key for buyer'\n )\n assert(\n this.checkSig(buyerSig, buyerPubKey),\n 'buyer signature check failed'\n )\n\n // Require nLocktime enabled https://wiki.bitcoinsv.io/index.php/NLocktime_and_nSequence\n assert(\n this.ctx.sequence < UINT_MAX,\n 'require nLocktime enabled'\n )\n\n // Check if using block height.\n if (this.deadline < LOCKTIME_BLOCK_HEIGHT_MARKER) {\n // Enforce nLocktime field to also use block height.\n assert(\n this.ctx.locktime < LOCKTIME_BLOCK_HEIGHT_MARKER\n )\n }\n assert(this.ctx.locktime >= this.deadline, 'deadline not yet reached')\n\n // Ensure buyer gets refund.\n const amount = this.ctx.utxo.value\n const out = Utils.buildPublicKeyHashOutput(this.buyerAddr, amount)\n assert(hash256(out) == this.ctx.hashOutputs, 'hashOutputs mismatch')\n}\n")),(0,i.kt)("p",null,"The method checks the buyers signature validity. It also checks the transaction nLocktime value, to ensure it can be accepted by miners only after the deadline."),(0,i.kt)("h2",{id:"conclusion"},"Conclusion"),(0,i.kt)("p",null,"Congratulations! You have completed the escrow tutorial!"),(0,i.kt)("p",null,"The full code can be found in our ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/sCrypt-Inc/boilerplate/blob/master/src/contracts/multisigEscrow.ts"},"boilerplate repository"),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/main.0d51a83c.js b/assets/js/main.0d51a83c.js new file mode 100644 index 000000000..6bdd485c0 --- /dev/null +++ b/assets/js/main.0d51a83c.js @@ -0,0 +1,2 @@ +/*! For license information please see main.0d51a83c.js.LICENSE.txt */ +(self.webpackChunkscrypt_docs=self.webpackChunkscrypt_docs||[]).push([[179],{830:(e,t,n)=>{"use strict";n.d(t,{W:()=>a});var r=n(7294);function a(){return r.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},r.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}},723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var r=n(7294),a=n(7462),o=n(8356),i=n.n(o),s=n(6887);const l={"01e59a88":[()=>n.e(7738).then(n.bind(n,3553)),"@site/docs/tutorials/tic-tac-toe.md",3553],"03e490ce":[()=>n.e(2462).then(n.bind(n,3164)),"@site/docs/reference/interfaces/SubscribeOptions.md",3164],"0480b142":[()=>n.e(836).then(n.bind(n,3584)),"@site/docs/faq.md",3584],"06de43e0":[()=>n.e(1567).then(n.bind(n,429)),"@site/docs/reference/modules/bsv.Networks.md",429],"07109bdf":[()=>n.e(2006).then(n.t.bind(n,7085,19)),"/github/workspace/.docusaurus/docusaurus-theme-search-algolia/default/plugin-route-context-module-100.json",7085],"0ccfb315":[()=>n.e(2328).then(n.bind(n,2502)),"@site/docs/reference/interfaces/TxInputRef.md",2502],"10d519e3":[()=>n.e(2217).then(n.bind(n,9252)),"@site/docs/reference/classes/bsv.ECIES.md",9252],"138eedef":[()=>n.e(8881).then(n.bind(n,8008)),"@site/docs/reference/classes/bsv.HDPublicKey.md",8008],"14155be4":[()=>n.e(1217).then(n.bind(n,7792)),"@site/docs/reference/interfaces/SignTransactionOptions.md",7792],"14b44c09":[()=>n.e(462).then(n.bind(n,2083)),"@site/docs/reference/classes/bsv.crypto.Point.md",2083],"14eb3368":[()=>Promise.all([n.e(532),n.e(9817)]).then(n.bind(n,4228)),"@theme/DocCategoryGeneratedIndexPage",4228],"1788e182":[()=>n.e(2813).then(n.bind(n,7560)),"@site/docs/how-to-integrate-a-frontend/how-to-integrate-a-frontend.md",7560],17896441:[()=>Promise.all([n.e(532),n.e(7918)]).then(n.bind(n,5824)),"@theme/DocItem",5824],"17a77d31":[()=>n.e(6240).then(n.bind(n,6326)),"@site/docs/reference/classes/bsv.Transaction.Input-1.md",6326],"17b1a180":[()=>n.e(7839).then(n.bind(n,8623)),"@site/docs/reference/classes/bsv.encoding.Base58.md",8623],"19eca43a":[()=>n.e(9100).then(n.bind(n,7855)),"@site/docs/reference/classes/DefaultProvider.md",7855],"1a4e3797":[()=>Promise.all([n.e(532),n.e(7920)]).then(n.bind(n,3044)),"@theme/SearchPage",3044],"1a54843f":[()=>n.e(8150).then(n.t.bind(n,3775,19)),"~docs/default/category-tutorialsidebar-category-tutorials-1-91c.json",3775],"1a6f2b55":[()=>n.e(1689).then(n.bind(n,7937)),"@site/docs/reference/classes/bsv.Unit.md",7937],"1b1e1a52":[()=>n.e(8e3).then(n.bind(n,1689)),"@site/docs/advanced/inline-asm.md",1689],"1b23cebc":[()=>n.e(4030).then(n.bind(n,8261)),"@site/docs/reference/classes/bsv.Transaction.UnspentOutput.md",8261],"1be78505":[()=>Promise.all([n.e(532),n.e(9514)]).then(n.bind(n,9963)),"@theme/DocPage",9963],"1cb1071b":[()=>n.e(1316).then(n.bind(n,9755)),"@site/docs/reference/classes/Constants.md",9755],"1db64337":[()=>n.e(1372).then(n.bind(n,6777)),"@site/docs/overview.md",6777],"205159e4":[()=>n.e(8151).then(n.bind(n,6885)),"@site/docs/reference/modules/bsv.crypto.md",6885],"2594e5e6":[()=>n.e(6938).then(n.bind(n,3744)),"@site/docs/reference/interfaces/MethodCallOptions.md",3744],"26d5742a":[()=>n.e(7097).then(n.bind(n,2776)),"@site/docs/reference/modules/bsv.Transaction.Sighash.md",2776],"27431a05":[()=>n.e(6308).then(n.bind(n,3506)),"@site/docs/reference/enums/SignatureHashType.md",3506],"2920d9d5":[()=>n.e(8929).then(n.bind(n,7698)),"@site/docs/how-to-write-a-contract/scriptcontext.md",7698],"2ab2aa69":[()=>n.e(2807).then(n.bind(n,384)),"@site/docs/tutorials/oracle.md",384],"2d3d592f":[()=>n.e(8380).then(n.bind(n,6081)),"@site/docs/reference/classes/bsv.crypto.Signature.md",6081],"313836b0":[()=>n.e(4564).then(n.bind(n,2501)),"@site/docs/reference/interfaces/SignatureResponse.md",2501],"31d8d510":[()=>n.e(8413).then(n.bind(n,2610)),"@site/docs/reference/interfaces/bsv.crypto.IOpts.md",2610],"331ef79c":[()=>n.e(2895).then(n.bind(n,7621)),"@site/docs/reference/modules/bsv.crypto.ECDSA.md",7621],"33426d98":[()=>n.e(5065).then(n.bind(n,2329)),"@site/docs/reference/classes/ScryptProvider.md",2329],"33a4e2e3":[()=>n.e(3542).then(n.bind(n,1692)),"@site/docs/reference/classes/DotwalletSigner.md",1692],"3658c897":[()=>n.e(6091).then(n.bind(n,3971)),"@site/docs/reference/classes/bsv.Address.md",3971],"3666a527":[()=>n.e(9615).then(n.bind(n,8589)),"@site/docs/how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx.md",8589],"38b1c6c6":[()=>n.e(3690).then(n.bind(n,8958)),"@site/docs/advanced/how-to-build-an-oracle-service.md",8958],"3b8c55ea":[()=>n.e(3217).then(n.bind(n,9250)),"@site/docs/installation.md",9250],"3bac039d":[()=>n.e(4734).then(n.bind(n,9306)),"@site/docs/tokens/tutorials/inscribe-image.md",9306],"3d41d66e":[()=>n.e(5330).then(n.bind(n,7487)),"@site/docs/reference/interfaces/MethodCallTxBuilder.md",7487],"3d8a8d1b":[()=>n.e(1168).then(n.bind(n,2177)),"@site/docs/reference/classes/WhatsonchainProvider.md",2177],"3ff43f10":[()=>n.e(5294).then(n.t.bind(n,6086,19)),"~docs/default/category-tutorialsidebar-category-advanced-263.json",6086],"419555a2":[()=>n.e(1712).then(n.bind(n,7597)),"@site/docs/reference/classes/bsv.crypto.BN.md",7597],"440910b0":[()=>n.e(7944).then(n.bind(n,3377)),"@site/docs/reference/classes/bsv.BlockHeader.md",3377],"45c8a2be":[()=>n.e(4661).then(n.bind(n,4619)),"@site/docs/advanced/how-to-add-a-signer.md",4619],"47d5ee98":[()=>n.e(8005).then(n.bind(n,8293)),"@site/docs/reference/modules/bsv.Script.md",8293],"4ace2938":[()=>n.e(4709).then(n.bind(n,8974)),"@site/docs/reference/interfaces/ContractCalledEvent.md",8974],"4af4b6e8":[()=>n.e(1826).then(n.bind(n,3614)),"@site/docs/reference/classes/GorillapoolProvider.md",3614],"4c37cee5":[()=>n.e(2441).then(n.bind(n,4909)),"@site/docs/advanced/sighash-type.md",4909],"4d00a19e":[()=>n.e(966).then(n.bind(n,4660)),"@site/docs/reference/classes/bsv.encoding.Base58Check.md",4660],"4d48c635":[()=>n.e(4759).then(n.t.bind(n,3769,19)),"/github/workspace/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],"4e65a820":[()=>n.e(7966).then(n.bind(n,1318)),"@site/docs/how-to-deploy-and-call-a-contract/deploy-cli.md",1318],"50b48b43":[()=>n.e(6384).then(n.bind(n,8692)),"@site/docs/tokens/tutorials/mint-bsv20-v2.md",8692],"51cfe601":[()=>n.e(6201).then(n.bind(n,7818)),"@site/docs/reference/modules/bsv.crypto.Random.md",7818],"51d1dba0":[()=>n.e(1636).then(n.bind(n,7954)),"@site/docs/how-to-deploy-and-call-a-contract/call-deployed.md",7954],"54547e85":[()=>n.e(9404).then(n.bind(n,3170)),"@site/docs/tutorials/hello-world.md",3170],"5455d950":[()=>n.e(5120).then(n.bind(n,2774)),"@site/docs/reference/classes/bsv.HDPrivateKey.md",2774],55201687:[()=>n.e(5994).then(n.bind(n,7419)),"@site/docs/reference/interfaces/bsv.Script.Interpreter.InterpretState.md",7419],"558c5b2f":[()=>n.e(8199).then(n.bind(n,796)),"@site/docs/tutorials/ordinal-auction.md",796],"5637ccf6":[()=>n.e(5020).then(n.bind(n,4598)),"@site/docs/tokens/tutorials/mint-bsv20-v1.md",4598],"56b58987":[()=>n.e(3040).then(n.bind(n,5046)),"@site/docs/reference/interfaces/MultiContractCallOptions.md",5046],"56d75774":[()=>n.e(4088).then(n.t.bind(n,5745,19)),"/github/workspace/.docusaurus/docusaurus-plugin-content-pages/default/plugin-route-context-module-100.json",5745],"572d3f0b":[()=>n.e(6325).then(n.bind(n,6112)),"@site/docs/tokens/nft/nft.md",6112],"5ba26743":[()=>n.e(3841).then(n.bind(n,1953)),"@site/docs/reference/interfaces/StatefulNext.md",1953],"5e70887e":[()=>n.e(9147).then(n.bind(n,9980)),"@site/docs/reference/classes/bsv.encoding.BufferWriter.md",9980],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,6809)),"@generated/docusaurus.config",6809],"61e13606":[()=>n.e(3808).then(n.bind(n,8214)),"@site/docs/reference/interfaces/TxContext.md",8214],"6484c565":[()=>n.e(7147).then(n.bind(n,6740)),"@site/docs/reference/interfaces/bsv.Networks.Network.md",6740],66540400:[()=>n.e(5937).then(n.bind(n,5183)),"@site/docs/reference/classes/SmartContract.md",5183],"67ff73b9":[()=>n.e(2317).then(n.bind(n,4790)),"@site/docs/reference/interfaces/ScryptConfig.md",4790],"6958f4b4":[()=>n.e(6341).then(n.bind(n,3878)),"@site/docs/how-to-test-a-contract.md",3878],"69c71146":[()=>n.e(6364).then(n.bind(n,1819)),"@site/docs/ethereum-devs.md",1819],"6c2dbd7a":[()=>n.e(6857).then(n.bind(n,6029)),"@site/docs/tokens/tokens.md",6029],"6d1a890e":[()=>n.e(9442).then(n.bind(n,5869)),"@site/docs/advanced/codeseparator.md",5869],"6d80b1c2":[()=>n.e(8203).then(n.bind(n,5841)),"@site/docs/reference/classes/SigHash.md",5841],"6eaa7f88":[()=>n.e(7154).then(n.bind(n,4616)),"@site/docs/advanced/how-to-replay-instance.md",4616],"6ed84bca":[()=>n.e(100).then(n.bind(n,9151)),"@site/docs/reference/interfaces/MultiContractTransaction.md",9151],"70db8588":[()=>n.e(21).then(n.bind(n,183)),"@site/docs/reference/interfaces/ScriptContext.md",183],"7225f144":[()=>n.e(208).then(n.bind(n,1731)),"@site/docs/reference/classes/HashedMap.md",1731],"727923c4":[()=>n.e(3732).then(n.bind(n,7974)),"@site/docs/reference/classes/bsv.Script.Interpreter-1.md",7974],"7381381c":[()=>n.e(7701).then(n.bind(n,2767)),"@site/docs/reference/classes/Signer.md",2767],"73e21f82":[()=>n.e(275).then(n.bind(n,1277)),"@site/docs/advanced/how-to-call-multiple-contracts.md",1277],"74e275e2":[()=>n.e(1112).then(n.bind(n,8920)),"@site/docs/how-to-deploy-and-call-a-contract/faucet.md",8920],"74f9bace":[()=>n.e(8142).then(n.bind(n,3568)),"@site/docs/reference/classes/bsv.Transaction.Output.md",3568],"77dda5d6":[()=>n.e(2018).then(n.bind(n,3242)),"@site/docs/how-to-publish-a-contract.md",3242],"787f7b6d":[()=>n.e(8245).then(n.bind(n,9412)),"@site/docs/reference/interfaces/bsv.Script.IOpChunk.md",9412],"7b430b5d":[()=>n.e(4568).then(n.bind(n,8510)),"@site/docs/reference/classes/VarIntWriter.md",8510],"7c4be5dd":[()=>n.e(589).then(n.bind(n,7176)),"@site/docs/reference/classes/DummyProvider.md",7176],"7d4560fc":[()=>n.e(8944).then(n.bind(n,6250)),"@site/docs/reference/classes/TAALSigner.md",6250],"7fde2f23":[()=>n.e(8062).then(n.bind(n,292)),"@site/docs/reference/interfaces/UtxoQueryOptions.md",292],"80d01892":[()=>n.e(3139).then(n.bind(n,9894)),"@site/docs/reference/classes/TaalProvider.md",9894],"82e67270":[()=>n.e(3204).then(n.bind(n,3681)),"@site/docs/reference/classes/Provider.md",3681],"83e3cb0c":[()=>n.e(4428).then(n.bind(n,4093)),"@site/docs/reference/modules/bsv.Transaction.Input.md",4093],"83f962c1":[()=>n.e(3826).then(n.bind(n,8656)),"@site/docs/reference/classes/SensiletSigner.md",8656],"83fb1adc":[()=>n.e(1220).then(n.bind(n,370)),"@site/docs/reference/interfaces/bsv.Util.md",370],"862d9758":[()=>n.e(5636).then(n.bind(n,2010)),"@site/docs/reference/interfaces/TxOutputRef.md",2010],"874dec39":[()=>n.e(3317).then(n.bind(n,6165)),"@site/docs/reference/modules/bsv.crypto.Hash.md",6165],"879ebe09":[()=>n.e(2185).then(n.bind(n,2302)),"@site/docs/reference/modules/bsv.Script.Interpreter.md",2302],"8c1b62a1":[()=>n.e(55).then(n.bind(n,9844)),"@site/docs/advanced/How to only sign p2pkh inputs.md",9844],"8e2eb00b":[()=>n.e(6297).then(n.bind(n,4343)),"@site/docs/how-to-write-a-contract/stateful-contract.md",4343],"910cd6a4":[()=>n.e(2).then(n.bind(n,2728)),"@site/docs/tokens/ft/existing.md",2728],"912ef652":[()=>n.e(2287).then(n.bind(n,9379)),"@site/docs/reference/modules/bsv.Transaction.md",9379],"924f1c1c":[()=>n.e(4560).then(n.bind(n,2942)),"@site/docs/reference/classes/bsv.Transaction-1.md",2942],"9277e5e6":[()=>n.e(2997).then(n.bind(n,3552)),"@site/docs/tokens/ft/multiple.md",3552],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"9b05ebac":[()=>n.e(7945).then(n.bind(n,4450)),"@site/docs/reference/classes/bsv.Transaction.Input.PublicKeyHash.md",4450],"9bd2e2d8":[()=>n.e(3392).then(n.bind(n,8636)),"@site/docs/reference/README.md",8636],"9bda8f72":[()=>n.e(3016).then(n.bind(n,6545)),"@site/docs/reference/interfaces/ContractTransaction.md",6545],"9e9f554b":[()=>n.e(2106).then(n.bind(n,9460)),"@site/docs/reference/modules/bsv.encoding.md",9460],"9fc92457":[()=>n.e(980).then(n.bind(n,2412)),"@site/docs/reference/classes/VarIntReader.md",2412],"9fcad7a3":[()=>n.e(2890).then(n.bind(n,4676)),"@site/docs/reference/classes/bsv.Block.md",4676],"9fea62fb":[()=>n.e(4337).then(n.bind(n,1005)),"@site/docs/reference/classes/bsv.Message.md",1005],a1bc6bc5:[()=>n.e(7333).then(n.bind(n,827)),"@site/docs/reference/classes/Utils.md",827],a5c7ba44:[()=>n.e(7062).then(n.bind(n,9475)),"@site/docs/tokens/ft/ft.md",9475],a7d37132:[()=>n.e(2894).then(n.bind(n,3182)),"@site/docs/reference/interfaces/Outpoint.md",3182],a7e31d84:[()=>n.e(3012).then(n.bind(n,7198)),"@site/docs/reference/classes/BsvApi.md",7198],ad5627e3:[()=>n.e(9968).then(n.bind(n,8351)),"@site/docs/reference/classes/TestWallet.md",8351],adc4c70f:[()=>n.e(7653).then(n.bind(n,4842)),"@site/docs/how-to-deploy-and-call-a-contract/how-to-deploy-and-call-a-contract.md",4842],b16c2f66:[()=>n.e(4346).then(n.bind(n,4520)),"@site/docs/advanced/timeLock.md",4520],b40963c8:[()=>n.e(5700).then(n.bind(n,6185)),"@site/docs/how-to-debug-a-contract.md",6185],b47ebff3:[()=>n.e(704).then(n.bind(n,7945)),"@site/docs/reference/interfaces/DefaultProviderOption.md",7945],b6325b43:[()=>n.e(8241).then(n.bind(n,2203)),"@site/docs/reference/classes/HashedSet.md",2203],b7851e83:[()=>n.e(4617).then(n.bind(n,639)),"@site/docs/how-to-write-a-contract/built-ins.md",639],b7e6597b:[()=>n.e(6672).then(n.bind(n,9571)),"@site/docs/advanced/how-to-integrate-scrypt-service.md",9571],b99126ff:[()=>n.e(4141).then(n.bind(n,8694)),"@site/docs/reference/classes/bsv.Transaction.Signature.md",8694],bb7a85de:[()=>n.e(351).then(n.bind(n,2786)),"@site/docs/how-to-integrate-a-frontend/how-to-integrate-dotwallet.md",2786],bd63771e:[()=>n.e(342).then(n.bind(n,4173)),"@site/docs/tokens/ft/woc-bsv20-plugin.md",4173],bffcfebc:[()=>n.e(2133).then(n.bind(n,2959)),"@site/docs/reference/classes/bsv.Mnemonic.md",2959],c023801b:[()=>n.e(2828).then(n.bind(n,3493)),"@site/docs/reference/interfaces/TransactionResponse.md",3493],c138b1fa:[()=>n.e(4831).then(n.bind(n,2731)),"@site/docs/reference/modules/bsv.md",2731],c186e46b:[()=>n.e(6138).then(n.bind(n,2652)),"@site/src/pages/overview.js",2652],c29255d2:[()=>n.e(4089).then(n.bind(n,9175)),"@site/docs/advanced/how-to-debug-scriptcontext.md",9175],c2959c58:[()=>n.e(3831).then(n.bind(n,2609)),"@site/docs/reference/classes/bsv.PublicKey.md",2609],c49c0ac4:[()=>n.e(5032).then(n.bind(n,2764)),"@site/docs/reference/classes/bsv.PrivateKey.md",2764],c5a48ac7:[()=>n.e(6647).then(n.bind(n,6182)),"@site/docs/bitcoin-basics/bitcoin-basics.md",6182],ca2c86a8:[()=>n.e(1403).then(n.bind(n,8989)),"@site/docs/tutorials/auction.md",8989],cb43a3ec:[()=>n.e(5090).then(n.bind(n,448)),"@site/docs/reference/interfaces/SignatureRequest.md",448],cef480a7:[()=>n.e(2653).then(n.bind(n,9414)),"@site/docs/reference/interfaces/LogConfig.md",9414],d17b93f5:[()=>n.e(1033).then(n.bind(n,230)),"@site/docs/bitcoin-basics/bsv.md",230],d795c046:[()=>n.e(8790).then(n.bind(n,5825)),"@site/docs/reference/classes/SmartContractLib.md",5825],db37e9c8:[()=>n.e(8567).then(n.bind(n,5937)),"@site/docs/tokens/nft/existing.md",5937],db986b04:[()=>n.e(1811).then(n.bind(n,1298)),"@site/docs/reference/classes/OpCode.md",1298],dc5aa0c6:[()=>n.e(9318).then(n.bind(n,3017)),"@site/docs/reference/classes/bsv.MerkleBlock.md",3017],dcd4f12c:[()=>n.e(9268).then(n.bind(n,5412)),"@site/docs/reference/classes/bsv.Opcode.md",5412],dd80477d:[()=>n.e(3689).then(n.bind(n,8726)),"@site/docs/advanced/how-to-add-a-provider.md",8726],e37cbbfc:[()=>n.e(7139).then(n.bind(n,2165)),"@site/docs/tutorials/escrow.md",2165],e38e2f24:[()=>n.e(4855).then(n.bind(n,1764)),"@site/docs/reference/interfaces/RequestConfig.md",1764],e3a53a02:[()=>n.e(8455).then(n.bind(n,9251)),"@site/docs/reference/interfaces/bsv.Transaction.IUnspentOutput.md",9251],e4e10033:[()=>n.e(759).then(n.bind(n,2489)),"@site/docs/reference/interfaces/VerifyResult.md",2489],e525704c:[()=>n.e(666).then(n.bind(n,651)),"@site/docs/reference/classes/SensibleProvider.md",651],e74d5bd3:[()=>n.e(9016).then(n.bind(n,4629)),"@site/docs/reference/classes/bsv.Script-1.md",4629],e97527cd:[()=>n.e(9322).then(n.bind(n,865)),"@site/docs/reference/interfaces/SubScription.md",865],ec4bed84:[()=>n.e(7105).then(n.bind(n,8425)),"@site/docs/tutorials/voting.md",8425],ee294475:[()=>n.e(8182).then(n.bind(n,5692)),"@site/docs/reference/interfaces/Artifact.md",5692],f0ad07a9:[()=>n.e(9517).then(n.bind(n,8267)),"@site/docs/how-to-verify-a-contract.md",8267],f0d18cf5:[()=>n.e(284).then(n.bind(n,188)),"@site/docs/reference/classes/ContractApi.md",188],f1af8fb8:[()=>n.e(6387).then(n.bind(n,3712)),"@site/docs/reference/classes/ActionError.md",3712],f5fbe228:[()=>n.e(2705).then(n.bind(n,1713)),"@site/docs/reference/classes/FunctionCall.md",1713],f7fb2808:[()=>n.e(4421).then(n.t.bind(n,8862,19)),"~docs/default/category-tutorialsidebar-category-tutorials-b01.json",8862],f8498202:[()=>n.e(4440).then(n.bind(n,3595)),"@site/docs/tokens/tutorials/ordinal-lock.md",3595],fa011ef2:[()=>n.e(4999).then(n.bind(n,3386)),"@site/docs/reference/enums/ProviderEvent.md",3386],fa01f05c:[()=>n.e(2969).then(n.bind(n,8978)),"@site/docs/how-to-write-a-contract/how-to-write-a-contract.md",8978],fd8c99ae:[()=>n.e(3525).then(n.bind(n,1810)),"@site/docs/reference/classes/bsv.encoding.Varint.md",1810],fe61ad06:[()=>n.e(7719).then(n.bind(n,8141)),"@site/docs/tutorials/zkp.md",8141],ff282309:[()=>n.e(9348).then(n.bind(n,1404)),"@site/docs/reference/classes/bsv.encoding.BufferReader.md",1404]};function c(e){let{error:t,retry:n,pastDelay:a}=e;return t?r.createElement("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"}},r.createElement("p",null,String(t)),r.createElement("div",null,r.createElement("button",{type:"button",onClick:n},"Retry"))):a?r.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"}},r.createElement("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb"},r.createElement("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2"},r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"8"},r.createElement("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"}))))):null}var u=n(9670),d=n(226);function f(e,t){if("*"===e)return i()({loading:c,loader:()=>n.e(4972).then(n.bind(n,4972)),modules:["@theme/NotFound"],webpack:()=>[4972],render(e,t){const n=e.default;return r.createElement(d.z,{value:{plugin:{name:"native",id:"default"}}},r.createElement(n,t))}});const o=s[`${e}-${t}`],f={},p=[],m=[],h=(0,u.Z)(o);return Object.entries(h).forEach((e=>{let[t,n]=e;const r=l[n];r&&(f[t]=r[0],p.push(r[1]),m.push(r[2]))})),i().Map({loading:c,loader:f,modules:p,webpack:()=>m,render(t,n){const i=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let o=i;const s=n.split(".");s.slice(0,-1).forEach((e=>{o=o[e]})),o[s[s.length-1]]=a}));const s=i.__comp;delete i.__comp;const l=i.__context;return delete i.__context,r.createElement(d.z,{value:l},r.createElement(s,(0,a.Z)({},i,n)))}})}const p=[{path:"/overview",component:f("/overview","775"),exact:!0},{path:"/search",component:f("/search","10f"),exact:!0},{path:"/",component:f("/","526"),routes:[{path:"/",component:f("/","dc5"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/codeseparator",component:f("/advanced/codeseparator","4c2"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/How to only sign p2pkh inputs",component:f("/advanced/How to only sign p2pkh inputs","aed"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/how-to-add-a-provider",component:f("/advanced/how-to-add-a-provider","bd3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/how-to-add-a-signer",component:f("/advanced/how-to-add-a-signer","e82"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/how-to-build-an-oracle-service",component:f("/advanced/how-to-build-an-oracle-service","7e1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/how-to-call-multiple-contracts",component:f("/advanced/how-to-call-multiple-contracts","cb2"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/how-to-debug-scriptcontext",component:f("/advanced/how-to-debug-scriptcontext","cf6"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/how-to-integrate-scrypt-service",component:f("/advanced/how-to-integrate-scrypt-service","250"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/how-to-replay-instance",component:f("/advanced/how-to-replay-instance","b3e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/inline-asm",component:f("/advanced/inline-asm","968"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/sighash-type",component:f("/advanced/sighash-type","dd9"),exact:!0,sidebar:"tutorialSidebar"},{path:"/advanced/timeLock",component:f("/advanced/timeLock","c71"),exact:!0,sidebar:"tutorialSidebar"},{path:"/bitcoin-basics/",component:f("/bitcoin-basics/","364"),exact:!0,sidebar:"tutorialSidebar"},{path:"/bitcoin-basics/bsv",component:f("/bitcoin-basics/bsv","339"),exact:!0,sidebar:"tutorialSidebar"},{path:"/category/advanced",component:f("/category/advanced","5f4"),exact:!0,sidebar:"tutorialSidebar"},{path:"/category/tutorials",component:f("/category/tutorials","6d7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/category/tutorials-1",component:f("/category/tutorials-1","d08"),exact:!0,sidebar:"tutorialSidebar"},{path:"/ethereum-devs",component:f("/ethereum-devs","aea"),exact:!0,sidebar:"tutorialSidebar"},{path:"/faq",component:f("/faq","204"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-debug-a-contract",component:f("/how-to-debug-a-contract","e00"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-deploy-and-call-a-contract/",component:f("/how-to-deploy-and-call-a-contract/","c9a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-deploy-and-call-a-contract/call-deployed",component:f("/how-to-deploy-and-call-a-contract/call-deployed","a5f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-deploy-and-call-a-contract/deploy-cli",component:f("/how-to-deploy-and-call-a-contract/deploy-cli","d4b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-deploy-and-call-a-contract/faucet",component:f("/how-to-deploy-and-call-a-contract/faucet","40f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx",component:f("/how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx","dd8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-integrate-a-frontend/",component:f("/how-to-integrate-a-frontend/","fc3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-integrate-a-frontend/how-to-integrate-dotwallet",component:f("/how-to-integrate-a-frontend/how-to-integrate-dotwallet","6dc"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-publish-a-contract",component:f("/how-to-publish-a-contract","884"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-test-a-contract",component:f("/how-to-test-a-contract","5b9"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-verify-a-contract",component:f("/how-to-verify-a-contract","c41"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-write-a-contract/",component:f("/how-to-write-a-contract/","d64"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-write-a-contract/built-ins",component:f("/how-to-write-a-contract/built-ins","58b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-write-a-contract/scriptcontext",component:f("/how-to-write-a-contract/scriptcontext","07f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/how-to-write-a-contract/stateful-contract",component:f("/how-to-write-a-contract/stateful-contract","3ea"),exact:!0,sidebar:"tutorialSidebar"},{path:"/installation",component:f("/installation","2e7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/",component:f("/reference/","a0f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/ActionError",component:f("/reference/classes/ActionError","e70"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Address",component:f("/reference/classes/bsv.Address","9b3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Block",component:f("/reference/classes/bsv.Block","b5d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.BlockHeader",component:f("/reference/classes/bsv.BlockHeader","5ab"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.crypto.BN",component:f("/reference/classes/bsv.crypto.BN","155"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.crypto.Point",component:f("/reference/classes/bsv.crypto.Point","cdd"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.crypto.Signature",component:f("/reference/classes/bsv.crypto.Signature","94c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.ECIES",component:f("/reference/classes/bsv.ECIES","264"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.encoding.Base58",component:f("/reference/classes/bsv.encoding.Base58","950"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.encoding.Base58Check",component:f("/reference/classes/bsv.encoding.Base58Check","1e5"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.encoding.BufferReader",component:f("/reference/classes/bsv.encoding.BufferReader","3c0"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.encoding.BufferWriter",component:f("/reference/classes/bsv.encoding.BufferWriter","f7a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.encoding.Varint",component:f("/reference/classes/bsv.encoding.Varint","30d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.HDPrivateKey",component:f("/reference/classes/bsv.HDPrivateKey","6b4"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.HDPublicKey",component:f("/reference/classes/bsv.HDPublicKey","ca3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.MerkleBlock",component:f("/reference/classes/bsv.MerkleBlock","4a4"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Message",component:f("/reference/classes/bsv.Message","6e1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Mnemonic",component:f("/reference/classes/bsv.Mnemonic","d30"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Opcode",component:f("/reference/classes/bsv.Opcode","778"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.PrivateKey",component:f("/reference/classes/bsv.PrivateKey","414"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.PublicKey",component:f("/reference/classes/bsv.PublicKey","753"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Script-1",component:f("/reference/classes/bsv.Script-1","f77"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Script.Interpreter-1",component:f("/reference/classes/bsv.Script.Interpreter-1","3f7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Transaction-1",component:f("/reference/classes/bsv.Transaction-1","5a5"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Transaction.Input-1",component:f("/reference/classes/bsv.Transaction.Input-1","415"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Transaction.Input.PublicKeyHash",component:f("/reference/classes/bsv.Transaction.Input.PublicKeyHash","3af"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Transaction.Output",component:f("/reference/classes/bsv.Transaction.Output","75b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Transaction.Signature",component:f("/reference/classes/bsv.Transaction.Signature","38a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Transaction.UnspentOutput",component:f("/reference/classes/bsv.Transaction.UnspentOutput","dfa"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/bsv.Unit",component:f("/reference/classes/bsv.Unit","c37"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/BsvApi",component:f("/reference/classes/BsvApi","e86"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/Constants",component:f("/reference/classes/Constants","9b9"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/ContractApi",component:f("/reference/classes/ContractApi","a00"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/DefaultProvider",component:f("/reference/classes/DefaultProvider","70f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/DotwalletSigner",component:f("/reference/classes/DotwalletSigner","7ad"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/DummyProvider",component:f("/reference/classes/DummyProvider","6c3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/FunctionCall",component:f("/reference/classes/FunctionCall","d8b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/GorillapoolProvider",component:f("/reference/classes/GorillapoolProvider","5d8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/HashedMap",component:f("/reference/classes/HashedMap","998"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/HashedSet",component:f("/reference/classes/HashedSet","42d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/OpCode",component:f("/reference/classes/OpCode","d91"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/Provider",component:f("/reference/classes/Provider","0b7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/ScryptProvider",component:f("/reference/classes/ScryptProvider","536"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/SensibleProvider",component:f("/reference/classes/SensibleProvider","840"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/SensiletSigner",component:f("/reference/classes/SensiletSigner","806"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/SigHash",component:f("/reference/classes/SigHash","82d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/Signer",component:f("/reference/classes/Signer","554"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/SmartContract",component:f("/reference/classes/SmartContract","2ba"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/SmartContractLib",component:f("/reference/classes/SmartContractLib","628"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/TaalProvider",component:f("/reference/classes/TaalProvider","1c1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/TAALSigner",component:f("/reference/classes/TAALSigner","d37"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/TestWallet",component:f("/reference/classes/TestWallet","266"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/Utils",component:f("/reference/classes/Utils","934"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/VarIntReader",component:f("/reference/classes/VarIntReader","c9a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/VarIntWriter",component:f("/reference/classes/VarIntWriter","ff2"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/classes/WhatsonchainProvider",component:f("/reference/classes/WhatsonchainProvider","2b8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/enums/ProviderEvent",component:f("/reference/enums/ProviderEvent","c17"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/enums/SignatureHashType",component:f("/reference/enums/SignatureHashType","566"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/Artifact",component:f("/reference/interfaces/Artifact","a55"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/bsv.crypto.IOpts",component:f("/reference/interfaces/bsv.crypto.IOpts","b99"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/bsv.Networks.Network",component:f("/reference/interfaces/bsv.Networks.Network","e11"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/bsv.Script.Interpreter.InterpretState",component:f("/reference/interfaces/bsv.Script.Interpreter.InterpretState","d69"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/bsv.Script.IOpChunk",component:f("/reference/interfaces/bsv.Script.IOpChunk","8c1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/bsv.Transaction.IUnspentOutput",component:f("/reference/interfaces/bsv.Transaction.IUnspentOutput","1ae"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/bsv.Util",component:f("/reference/interfaces/bsv.Util","345"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/ContractCalledEvent",component:f("/reference/interfaces/ContractCalledEvent","b8e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/ContractTransaction",component:f("/reference/interfaces/ContractTransaction","21b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/DefaultProviderOption",component:f("/reference/interfaces/DefaultProviderOption","011"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/LogConfig",component:f("/reference/interfaces/LogConfig","bc4"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/MethodCallOptions",component:f("/reference/interfaces/MethodCallOptions","5be"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/MethodCallTxBuilder",component:f("/reference/interfaces/MethodCallTxBuilder","a9c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/MultiContractCallOptions",component:f("/reference/interfaces/MultiContractCallOptions","37a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/MultiContractTransaction",component:f("/reference/interfaces/MultiContractTransaction","fb0"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/Outpoint",component:f("/reference/interfaces/Outpoint","bf4"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/RequestConfig",component:f("/reference/interfaces/RequestConfig","062"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/ScriptContext",component:f("/reference/interfaces/ScriptContext","a1e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/ScryptConfig",component:f("/reference/interfaces/ScryptConfig","bbc"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/SignatureRequest",component:f("/reference/interfaces/SignatureRequest","de4"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/SignatureResponse",component:f("/reference/interfaces/SignatureResponse","0da"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/SignTransactionOptions",component:f("/reference/interfaces/SignTransactionOptions","cec"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/StatefulNext",component:f("/reference/interfaces/StatefulNext","42f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/SubscribeOptions",component:f("/reference/interfaces/SubscribeOptions","39a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/SubScription",component:f("/reference/interfaces/SubScription","429"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/TransactionResponse",component:f("/reference/interfaces/TransactionResponse","b64"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/TxContext",component:f("/reference/interfaces/TxContext","cda"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/TxInputRef",component:f("/reference/interfaces/TxInputRef","dbc"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/TxOutputRef",component:f("/reference/interfaces/TxOutputRef","656"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/UtxoQueryOptions",component:f("/reference/interfaces/UtxoQueryOptions","db2"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/interfaces/VerifyResult",component:f("/reference/interfaces/VerifyResult","201"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv",component:f("/reference/modules/bsv","420"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.crypto",component:f("/reference/modules/bsv.crypto","56a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.crypto.ECDSA",component:f("/reference/modules/bsv.crypto.ECDSA","018"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.crypto.Hash",component:f("/reference/modules/bsv.crypto.Hash","540"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.crypto.Random",component:f("/reference/modules/bsv.crypto.Random","b3c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.encoding",component:f("/reference/modules/bsv.encoding","c5f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.Networks",component:f("/reference/modules/bsv.Networks","729"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.Script",component:f("/reference/modules/bsv.Script","5fd"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.Script.Interpreter",component:f("/reference/modules/bsv.Script.Interpreter","d66"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.Transaction",component:f("/reference/modules/bsv.Transaction","651"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.Transaction.Input",component:f("/reference/modules/bsv.Transaction.Input","b96"),exact:!0,sidebar:"tutorialSidebar"},{path:"/reference/modules/bsv.Transaction.Sighash",component:f("/reference/modules/bsv.Transaction.Sighash","a67"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/",component:f("/tokens/","c8f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/ft/",component:f("/tokens/ft/","a0c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/ft/existing",component:f("/tokens/ft/existing","7d5"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/ft/multiple",component:f("/tokens/ft/multiple","844"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/ft/woc-bsv20-plugin",component:f("/tokens/ft/woc-bsv20-plugin","02e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/nft/",component:f("/tokens/nft/","a60"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/nft/existing",component:f("/tokens/nft/existing","70b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/tutorials/inscribe-image",component:f("/tokens/tutorials/inscribe-image","704"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/tutorials/mint-bsv20-v1",component:f("/tokens/tutorials/mint-bsv20-v1","7ce"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/tutorials/mint-bsv20-v2",component:f("/tokens/tutorials/mint-bsv20-v2","d12"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tokens/tutorials/ordinal-lock",component:f("/tokens/tutorials/ordinal-lock","158"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tutorials/auction",component:f("/tutorials/auction","2ba"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tutorials/escrow",component:f("/tutorials/escrow","22d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tutorials/hello-world",component:f("/tutorials/hello-world","4e8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tutorials/oracle",component:f("/tutorials/oracle","34c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tutorials/ordinal-auction",component:f("/tutorials/ordinal-auction","fb0"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tutorials/tic-tac-toe",component:f("/tutorials/tic-tac-toe","4db"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tutorials/voting",component:f("/tutorials/voting","28b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/tutorials/zkp",component:f("/tutorials/zkp","736"),exact:!0,sidebar:"tutorialSidebar"}]},{path:"*",component:f("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,t:()=>o});var r=n(7294);const a=r.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{o(!0)}),[]),r.createElement(a.Provider,{value:n},t)}},9383:(e,t,n)=>{"use strict";var r=n(7294),a=n(3935),o=n(3727),i=n(405),s=n(412);const l=[n(2497),n(3310),n(8320),n(2295)];var c=n(723),u=n(6550),d=n(8790);function f(e){let{children:t}=e;return r.createElement(r.Fragment,null,t)}var p=n(7462),m=n(5742),h=n(2263),b=n(4996),g=n(6668),v=n(833),y=n(4711),w=n(9727),S=n(3320),k=n(197);function E(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,h.Z)(),n=(0,y.l)();return r.createElement(m.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:a}]=e;return r.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:a})})),r.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function x(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.Z)(),a=function(){const{siteConfig:{url:e}}=(0,h.Z)(),{pathname:t}=(0,u.TH)();return e+(0,b.Z)(t)}(),o=t?`${n}${t}`:a;return r.createElement(m.Z,null,r.createElement("meta",{property:"og:url",content:o}),r.createElement("link",{rel:"canonical",href:o}))}function _(){const{i18n:{currentLocale:e}}=(0,h.Z)(),{metadata:t,image:n}=(0,g.L)();return r.createElement(r.Fragment,null,r.createElement(m.Z,null,r.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),r.createElement("body",{className:w.h})),n&&r.createElement(v.d,{image:n}),r.createElement(x,null),r.createElement(E,null),r.createElement(k.Z,{tag:S.HX,locale:e}),r.createElement(m.Z,null,t.map(((e,t)=>r.createElement("meta",(0,p.Z)({key:t},e))))))}const C=new Map;function T(e){if(C.has(e.pathname))return{...e,pathname:C.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return C.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return C.set(e.pathname,t),{...e,pathname:t}}var A=n(8934),P=n(8940);function O(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{var r;const a=(null==(r=t.default)?void 0:r[e])??t[e];return null==a?void 0:a(...n)}));return()=>a.forEach((e=>null==e?void 0:e()))}const R=function(e){let{children:t,location:n,previousLocation:a}=e;return(0,r.useLayoutEffect)((()=>{a!==n&&(a&&function(e){const{hash:t}=e;if(t){const e=decodeURIComponent(t.substring(1)),n=document.getElementById(e);null==n||n.scrollIntoView()}else window.scrollTo(0,0)}(n),O("onRouteDidUpdate",{previousLocation:a,location:n}))}),[a,n]),t};function L(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>null==e.route.component.preload?void 0:e.route.component.preload())))}class I extends r.Component{constructor(e){super(e),this.previousLocation=void 0,this.routeUpdateCleanupCb=void 0,this.previousLocation=null,this.routeUpdateCleanupCb=s.Z.canUseDOM?O("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=O("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),L(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return r.createElement(R,{previousLocation:this.previousLocation,location:t},r.createElement(u.AW,{location:t,render:()=>e}))}}const N=I,D="docusaurus-base-url-issue-banner-container",M="docusaurus-base-url-issue-banner-suggestion-container",B="__DOCUSAURUS_INSERT_BASEURL_BANNER";function F(e){return`\nwindow['${B}'] = true;\n\ndocument.addEventListener('DOMContentLoaded', maybeInsertBanner);\n\nfunction maybeInsertBanner() {\n var shouldInsert = window['${B}'];\n shouldInsert && insertBanner();\n}\n\nfunction insertBanner() {\n var bannerContainer = document.getElementById('${D}');\n if (!bannerContainer) {\n return;\n }\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{window[B]=!1}),[]),r.createElement(r.Fragment,null,!s.Z.canUseDOM&&r.createElement(m.Z,null,r.createElement("script",null,F(e))),r.createElement("div",{id:D}))}function U(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,h.Z)(),{pathname:n}=(0,u.TH)();return t&&n===e?r.createElement(j,null):null}function z(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:a,localeConfigs:o}}=(0,h.Z)(),i=(0,b.Z)(e),{htmlLang:s,direction:l}=o[a];return r.createElement(m.Z,null,r.createElement("html",{lang:s,dir:l}),r.createElement("title",null,t),r.createElement("meta",{property:"og:title",content:t}),r.createElement("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&r.createElement("meta",{name:"robots",content:"noindex, nofollow"}),e&&r.createElement("link",{rel:"icon",href:i}))}var $=n(4763);function H(){const e=(0,d.H)(c.Z),t=(0,u.TH)();return r.createElement($.Z,null,r.createElement(P.M,null,r.createElement(A.t,null,r.createElement(f,null,r.createElement(z,null),r.createElement(_,null),r.createElement(U,null),r.createElement(N,{location:T(t)},e)))))}var q=n(6887);const G=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{var r;if("undefined"==typeof document)return void n();const a=document.createElement("link");a.setAttribute("rel","prefetch"),a.setAttribute("href",e),a.onload=()=>t(),a.onerror=()=>n();const o=document.getElementsByTagName("head")[0]??(null==(r=document.getElementsByName("script")[0])?void 0:r.parentNode);null==o||o.appendChild(a)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var Z=n(9670);const V=new Set,W=new Set,K=()=>{var e,t;return(null==(e=navigator.connection)?void 0:e.effectiveType.includes("2g"))||(null==(t=navigator.connection)?void 0:t.saveData)},Y={prefetch(e){if(!(e=>!K()&&!W.has(e)&&!V.has(e))(e))return!1;V.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(q).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,Z.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?G(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!K()&&!W.has(e))(e)&&(W.add(e),L(e))},Q=Object.freeze(Y);if(s.Z.canUseDOM){window.docusaurus=Q;const e=a.hydrate;L(window.location.pathname).then((()=>{e(r.createElement(i.B6,null,r.createElement(o.VK,null,r.createElement(H,null))),document.getElementById("__docusaurus"))}))}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>u,M:()=>d});var r=n(7294),a=n(6809);const o=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/","versions":[{"name":"current","label":"Next","isLast":true,"path":"/","mainDocId":"overview","docs":[{"id":"advanced/codeseparator","path":"/advanced/codeseparator","sidebar":"tutorialSidebar"},{"id":"advanced/How to only sign p2pkh inputs","path":"/advanced/How to only sign p2pkh inputs","sidebar":"tutorialSidebar"},{"id":"advanced/how-to-add-a-provider","path":"/advanced/how-to-add-a-provider","sidebar":"tutorialSidebar"},{"id":"advanced/how-to-add-a-signer","path":"/advanced/how-to-add-a-signer","sidebar":"tutorialSidebar"},{"id":"advanced/how-to-build-an-oracle-service","path":"/advanced/how-to-build-an-oracle-service","sidebar":"tutorialSidebar"},{"id":"advanced/how-to-call-multiple-contracts","path":"/advanced/how-to-call-multiple-contracts","sidebar":"tutorialSidebar"},{"id":"advanced/how-to-debug-scriptcontext","path":"/advanced/how-to-debug-scriptcontext","sidebar":"tutorialSidebar"},{"id":"advanced/how-to-integrate-scrypt-service","path":"/advanced/how-to-integrate-scrypt-service","sidebar":"tutorialSidebar"},{"id":"advanced/how-to-replay-instance","path":"/advanced/how-to-replay-instance","sidebar":"tutorialSidebar"},{"id":"advanced/inline-asm","path":"/advanced/inline-asm","sidebar":"tutorialSidebar"},{"id":"advanced/sighash-type","path":"/advanced/sighash-type","sidebar":"tutorialSidebar"},{"id":"advanced/timeLock","path":"/advanced/timeLock","sidebar":"tutorialSidebar"},{"id":"bitcoin-basics/bitcoin-basics","path":"/bitcoin-basics/","sidebar":"tutorialSidebar"},{"id":"bitcoin-basics/bsv","path":"/bitcoin-basics/bsv","sidebar":"tutorialSidebar"},{"id":"ethereum-devs","path":"/ethereum-devs","sidebar":"tutorialSidebar"},{"id":"faq","path":"/faq","sidebar":"tutorialSidebar"},{"id":"how-to-debug-a-contract","path":"/how-to-debug-a-contract","sidebar":"tutorialSidebar"},{"id":"how-to-deploy-and-call-a-contract/call-deployed","path":"/how-to-deploy-and-call-a-contract/call-deployed","sidebar":"tutorialSidebar"},{"id":"how-to-deploy-and-call-a-contract/deploy-cli","path":"/how-to-deploy-and-call-a-contract/deploy-cli","sidebar":"tutorialSidebar"},{"id":"how-to-deploy-and-call-a-contract/faucet","path":"/how-to-deploy-and-call-a-contract/faucet","sidebar":"tutorialSidebar"},{"id":"how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx","path":"/how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx","sidebar":"tutorialSidebar"},{"id":"how-to-deploy-and-call-a-contract/how-to-deploy-and-call-a-contract","path":"/how-to-deploy-and-call-a-contract/","sidebar":"tutorialSidebar"},{"id":"how-to-integrate-a-frontend/how-to-integrate-a-frontend","path":"/how-to-integrate-a-frontend/","sidebar":"tutorialSidebar"},{"id":"how-to-integrate-a-frontend/how-to-integrate-dotwallet","path":"/how-to-integrate-a-frontend/how-to-integrate-dotwallet","sidebar":"tutorialSidebar"},{"id":"how-to-publish-a-contract","path":"/how-to-publish-a-contract","sidebar":"tutorialSidebar"},{"id":"how-to-test-a-contract","path":"/how-to-test-a-contract","sidebar":"tutorialSidebar"},{"id":"how-to-verify-a-contract","path":"/how-to-verify-a-contract","sidebar":"tutorialSidebar"},{"id":"how-to-write-a-contract/built-ins","path":"/how-to-write-a-contract/built-ins","sidebar":"tutorialSidebar"},{"id":"how-to-write-a-contract/how-to-write-a-contract","path":"/how-to-write-a-contract/","sidebar":"tutorialSidebar"},{"id":"how-to-write-a-contract/scriptcontext","path":"/how-to-write-a-contract/scriptcontext","sidebar":"tutorialSidebar"},{"id":"how-to-write-a-contract/stateful-contract","path":"/how-to-write-a-contract/stateful-contract","sidebar":"tutorialSidebar"},{"id":"installation","path":"/installation","sidebar":"tutorialSidebar"},{"id":"overview","path":"/","sidebar":"tutorialSidebar"},{"id":"reference/classes/ActionError","path":"/reference/classes/ActionError","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Address","path":"/reference/classes/bsv.Address","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Block","path":"/reference/classes/bsv.Block","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.BlockHeader","path":"/reference/classes/bsv.BlockHeader","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.crypto.BN","path":"/reference/classes/bsv.crypto.BN","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.crypto.Point","path":"/reference/classes/bsv.crypto.Point","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.crypto.Signature","path":"/reference/classes/bsv.crypto.Signature","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.ECIES","path":"/reference/classes/bsv.ECIES","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.encoding.Base58","path":"/reference/classes/bsv.encoding.Base58","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.encoding.Base58Check","path":"/reference/classes/bsv.encoding.Base58Check","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.encoding.BufferReader","path":"/reference/classes/bsv.encoding.BufferReader","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.encoding.BufferWriter","path":"/reference/classes/bsv.encoding.BufferWriter","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.encoding.Varint","path":"/reference/classes/bsv.encoding.Varint","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.HDPrivateKey","path":"/reference/classes/bsv.HDPrivateKey","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.HDPublicKey","path":"/reference/classes/bsv.HDPublicKey","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.MerkleBlock","path":"/reference/classes/bsv.MerkleBlock","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Message","path":"/reference/classes/bsv.Message","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Mnemonic","path":"/reference/classes/bsv.Mnemonic","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Opcode","path":"/reference/classes/bsv.Opcode","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.PrivateKey","path":"/reference/classes/bsv.PrivateKey","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.PublicKey","path":"/reference/classes/bsv.PublicKey","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Script-1","path":"/reference/classes/bsv.Script-1","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Script.Interpreter-1","path":"/reference/classes/bsv.Script.Interpreter-1","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Transaction-1","path":"/reference/classes/bsv.Transaction-1","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Transaction.Input-1","path":"/reference/classes/bsv.Transaction.Input-1","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Transaction.Input.PublicKeyHash","path":"/reference/classes/bsv.Transaction.Input.PublicKeyHash","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Transaction.Output","path":"/reference/classes/bsv.Transaction.Output","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Transaction.Signature","path":"/reference/classes/bsv.Transaction.Signature","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Transaction.UnspentOutput","path":"/reference/classes/bsv.Transaction.UnspentOutput","sidebar":"tutorialSidebar"},{"id":"reference/classes/bsv.Unit","path":"/reference/classes/bsv.Unit","sidebar":"tutorialSidebar"},{"id":"reference/classes/BsvApi","path":"/reference/classes/BsvApi","sidebar":"tutorialSidebar"},{"id":"reference/classes/Constants","path":"/reference/classes/Constants","sidebar":"tutorialSidebar"},{"id":"reference/classes/ContractApi","path":"/reference/classes/ContractApi","sidebar":"tutorialSidebar"},{"id":"reference/classes/DefaultProvider","path":"/reference/classes/DefaultProvider","sidebar":"tutorialSidebar"},{"id":"reference/classes/DotwalletSigner","path":"/reference/classes/DotwalletSigner","sidebar":"tutorialSidebar"},{"id":"reference/classes/DummyProvider","path":"/reference/classes/DummyProvider","sidebar":"tutorialSidebar"},{"id":"reference/classes/FunctionCall","path":"/reference/classes/FunctionCall","sidebar":"tutorialSidebar"},{"id":"reference/classes/GorillapoolProvider","path":"/reference/classes/GorillapoolProvider","sidebar":"tutorialSidebar"},{"id":"reference/classes/HashedMap","path":"/reference/classes/HashedMap","sidebar":"tutorialSidebar"},{"id":"reference/classes/HashedSet","path":"/reference/classes/HashedSet","sidebar":"tutorialSidebar"},{"id":"reference/classes/OpCode","path":"/reference/classes/OpCode","sidebar":"tutorialSidebar"},{"id":"reference/classes/Provider","path":"/reference/classes/Provider","sidebar":"tutorialSidebar"},{"id":"reference/classes/ScryptProvider","path":"/reference/classes/ScryptProvider","sidebar":"tutorialSidebar"},{"id":"reference/classes/SensibleProvider","path":"/reference/classes/SensibleProvider","sidebar":"tutorialSidebar"},{"id":"reference/classes/SensiletSigner","path":"/reference/classes/SensiletSigner","sidebar":"tutorialSidebar"},{"id":"reference/classes/SigHash","path":"/reference/classes/SigHash","sidebar":"tutorialSidebar"},{"id":"reference/classes/Signer","path":"/reference/classes/Signer","sidebar":"tutorialSidebar"},{"id":"reference/classes/SmartContract","path":"/reference/classes/SmartContract","sidebar":"tutorialSidebar"},{"id":"reference/classes/SmartContractLib","path":"/reference/classes/SmartContractLib","sidebar":"tutorialSidebar"},{"id":"reference/classes/TaalProvider","path":"/reference/classes/TaalProvider","sidebar":"tutorialSidebar"},{"id":"reference/classes/TAALSigner","path":"/reference/classes/TAALSigner","sidebar":"tutorialSidebar"},{"id":"reference/classes/TestWallet","path":"/reference/classes/TestWallet","sidebar":"tutorialSidebar"},{"id":"reference/classes/Utils","path":"/reference/classes/Utils","sidebar":"tutorialSidebar"},{"id":"reference/classes/VarIntReader","path":"/reference/classes/VarIntReader","sidebar":"tutorialSidebar"},{"id":"reference/classes/VarIntWriter","path":"/reference/classes/VarIntWriter","sidebar":"tutorialSidebar"},{"id":"reference/classes/WhatsonchainProvider","path":"/reference/classes/WhatsonchainProvider","sidebar":"tutorialSidebar"},{"id":"reference/enums/ProviderEvent","path":"/reference/enums/ProviderEvent","sidebar":"tutorialSidebar"},{"id":"reference/enums/SignatureHashType","path":"/reference/enums/SignatureHashType","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/Artifact","path":"/reference/interfaces/Artifact","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/bsv.crypto.IOpts","path":"/reference/interfaces/bsv.crypto.IOpts","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/bsv.Networks.Network","path":"/reference/interfaces/bsv.Networks.Network","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/bsv.Script.Interpreter.InterpretState","path":"/reference/interfaces/bsv.Script.Interpreter.InterpretState","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/bsv.Script.IOpChunk","path":"/reference/interfaces/bsv.Script.IOpChunk","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/bsv.Transaction.IUnspentOutput","path":"/reference/interfaces/bsv.Transaction.IUnspentOutput","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/bsv.Util","path":"/reference/interfaces/bsv.Util","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/ContractCalledEvent","path":"/reference/interfaces/ContractCalledEvent","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/ContractTransaction","path":"/reference/interfaces/ContractTransaction","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/DefaultProviderOption","path":"/reference/interfaces/DefaultProviderOption","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/LogConfig","path":"/reference/interfaces/LogConfig","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/MethodCallOptions","path":"/reference/interfaces/MethodCallOptions","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/MethodCallTxBuilder","path":"/reference/interfaces/MethodCallTxBuilder","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/MultiContractCallOptions","path":"/reference/interfaces/MultiContractCallOptions","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/MultiContractTransaction","path":"/reference/interfaces/MultiContractTransaction","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/Outpoint","path":"/reference/interfaces/Outpoint","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/RequestConfig","path":"/reference/interfaces/RequestConfig","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/ScriptContext","path":"/reference/interfaces/ScriptContext","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/ScryptConfig","path":"/reference/interfaces/ScryptConfig","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/SignatureRequest","path":"/reference/interfaces/SignatureRequest","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/SignatureResponse","path":"/reference/interfaces/SignatureResponse","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/SignTransactionOptions","path":"/reference/interfaces/SignTransactionOptions","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/StatefulNext","path":"/reference/interfaces/StatefulNext","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/SubscribeOptions","path":"/reference/interfaces/SubscribeOptions","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/SubScription","path":"/reference/interfaces/SubScription","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/TransactionResponse","path":"/reference/interfaces/TransactionResponse","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/TxContext","path":"/reference/interfaces/TxContext","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/TxInputRef","path":"/reference/interfaces/TxInputRef","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/TxOutputRef","path":"/reference/interfaces/TxOutputRef","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/UtxoQueryOptions","path":"/reference/interfaces/UtxoQueryOptions","sidebar":"tutorialSidebar"},{"id":"reference/interfaces/VerifyResult","path":"/reference/interfaces/VerifyResult","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv","path":"/reference/modules/bsv","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.crypto","path":"/reference/modules/bsv.crypto","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.crypto.ECDSA","path":"/reference/modules/bsv.crypto.ECDSA","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.crypto.Hash","path":"/reference/modules/bsv.crypto.Hash","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.crypto.Random","path":"/reference/modules/bsv.crypto.Random","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.encoding","path":"/reference/modules/bsv.encoding","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.Networks","path":"/reference/modules/bsv.Networks","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.Script","path":"/reference/modules/bsv.Script","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.Script.Interpreter","path":"/reference/modules/bsv.Script.Interpreter","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.Transaction","path":"/reference/modules/bsv.Transaction","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.Transaction.Input","path":"/reference/modules/bsv.Transaction.Input","sidebar":"tutorialSidebar"},{"id":"reference/modules/bsv.Transaction.Sighash","path":"/reference/modules/bsv.Transaction.Sighash","sidebar":"tutorialSidebar"},{"id":"reference/README","path":"/reference/","sidebar":"tutorialSidebar"},{"id":"tokens/ft/existing","path":"/tokens/ft/existing","sidebar":"tutorialSidebar"},{"id":"tokens/ft/ft","path":"/tokens/ft/","sidebar":"tutorialSidebar"},{"id":"tokens/ft/multiple","path":"/tokens/ft/multiple","sidebar":"tutorialSidebar"},{"id":"tokens/ft/woc-bsv20-plugin","path":"/tokens/ft/woc-bsv20-plugin","sidebar":"tutorialSidebar"},{"id":"tokens/nft/existing","path":"/tokens/nft/existing","sidebar":"tutorialSidebar"},{"id":"tokens/nft/nft","path":"/tokens/nft/","sidebar":"tutorialSidebar"},{"id":"tokens/tokens","path":"/tokens/","sidebar":"tutorialSidebar"},{"id":"tokens/tutorials/inscribe-image","path":"/tokens/tutorials/inscribe-image","sidebar":"tutorialSidebar"},{"id":"tokens/tutorials/mint-bsv20-v1","path":"/tokens/tutorials/mint-bsv20-v1","sidebar":"tutorialSidebar"},{"id":"tokens/tutorials/mint-bsv20-v2","path":"/tokens/tutorials/mint-bsv20-v2","sidebar":"tutorialSidebar"},{"id":"tokens/tutorials/ordinal-lock","path":"/tokens/tutorials/ordinal-lock","sidebar":"tutorialSidebar"},{"id":"tutorials/auction","path":"/tutorials/auction","sidebar":"tutorialSidebar"},{"id":"tutorials/escrow","path":"/tutorials/escrow","sidebar":"tutorialSidebar"},{"id":"tutorials/hello-world","path":"/tutorials/hello-world","sidebar":"tutorialSidebar"},{"id":"tutorials/oracle","path":"/tutorials/oracle","sidebar":"tutorialSidebar"},{"id":"tutorials/ordinal-auction","path":"/tutorials/ordinal-auction","sidebar":"tutorialSidebar"},{"id":"tutorials/tic-tac-toe","path":"/tutorials/tic-tac-toe","sidebar":"tutorialSidebar"},{"id":"tutorials/voting","path":"/tutorials/voting","sidebar":"tutorialSidebar"},{"id":"tutorials/zkp","path":"/tutorials/zkp","sidebar":"tutorialSidebar"},{"id":"/category/advanced","path":"/category/advanced","sidebar":"tutorialSidebar"},{"id":"/category/tutorials","path":"/category/tutorials","sidebar":"tutorialSidebar"},{"id":"/category/tutorials-1","path":"/category/tutorials-1","sidebar":"tutorialSidebar"}],"draftIds":[],"sidebars":{"tutorialSidebar":{"link":{"path":"/","label":"overview"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(7529);const l=JSON.parse('{"docusaurusVersion":"2.2.0","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.2.0"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"2.2.0"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"2.2.0"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.2.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.2.0"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"2.2.0"}}}'),c={siteConfig:a.default,siteMetadata:l,globalData:o,i18n:i,codeTranslations:s},u=r.createContext(c);function d(e){let{children:t}=e;return r.createElement(u.Provider,{value:c},t)}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var r=n(7294),a=n(412),o=n(5742),i=n(9889);function s(e){let{error:t,tryAgain:n}=e;return r.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",height:"50vh",width:"100%",fontSize:"20px"}},r.createElement("h1",null,"This page crashed."),r.createElement("p",null,t.message),r.createElement("button",{type:"button",onClick:n},"Try again"))}function l(e){let{error:t,tryAgain:n}=e;return r.createElement(u,{fallback:()=>r.createElement(s,{error:t,tryAgain:n})},r.createElement(o.Z,null,r.createElement("title",null,"Page Error")),r.createElement(i.Z,null,r.createElement(s,{error:t,tryAgain:n})))}const c=e=>r.createElement(l,e);class u extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){a.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??c)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,a={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(405);function o(e){return r.createElement(a.ql,e)}},9960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var r=n(7462),a=n(7294),o=n(3727),i=n(8780),s=n(2263),l=n(3919),c=n(412);const u=a.createContext({collectLink:()=>{}});var d=n(4996);function f(e,t){var n;let{isNavLink:f,to:p,href:m,activeClassName:h,isActive:b,"data-noBrokenLinkCheck":g,autoAddBaseUrl:v=!0,...y}=e;const{siteConfig:{trailingSlash:w,baseUrl:S}}=(0,s.Z)(),{withBaseUrl:k}=(0,d.C)(),E=(0,a.useContext)(u),x=(0,a.useRef)(null);(0,a.useImperativeHandle)(t,(()=>x.current));const _=p||m;const C=(0,l.Z)(_),T=null==_?void 0:_.replace("pathname://","");let A=void 0!==T?(P=T,v&&(e=>e.startsWith("/"))(P)?k(P):P):void 0;var P;A&&C&&(A=(0,i.applyTrailingSlash)(A,{trailingSlash:w,baseUrl:S}));const O=(0,a.useRef)(!1),R=f?o.OL:o.rU,L=c.Z.canUseIntersectionObserver,I=(0,a.useRef)(),N=()=>{O.current||null==A||(window.docusaurus.preload(A),O.current=!0)};(0,a.useEffect)((()=>(!L&&C&&null!=A&&window.docusaurus.prefetch(A),()=>{L&&I.current&&I.current.disconnect()})),[I,A,L,C]);const D=(null==(n=A)?void 0:n.startsWith("#"))??!1,M=!A||!C||D;return M||g||E.collectLink(A),M?a.createElement("a",(0,r.Z)({ref:x,href:A},_&&!C&&{target:"_blank",rel:"noopener noreferrer"},y)):a.createElement(R,(0,r.Z)({},y,{onMouseEnter:N,onTouchStart:N,innerRef:e=>{x.current=e,L&&e&&C&&(I.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(I.current.unobserve(e),I.current.disconnect(),null!=A&&window.docusaurus.prefetch(A))}))})),I.current.observe(e))},to:A},f&&{isActive:b,activeClassName:h}))}const p=a.forwardRef(f)},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l,I:()=>s});var r=n(7294);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=null==t?void 0:t[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var o=n(7529);function i(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return o[t??n]??n??t}function s(e,t){let{message:n,id:r}=e;return a(i({message:n,id:r}),t)}function l(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const s=i({message:t,id:n});return r.createElement(r.Fragment,null,a(s,o))}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>r});const r="default"},3919:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}n.d(t,{Z:()=>a,b:()=>r})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>o,Z:()=>i});var r=n(2263),a=n(3919);function o(){const{siteConfig:{baseUrl:e,url:t}}=(0,r.Z)();return{withBaseUrl:(n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:o=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,a.b)(n))return n;if(o)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,r)}}function i(e,t){void 0===t&&(t={});const{withBaseUrl:n}=o();return n(e,t)}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8940);function o(){return(0,r.useContext)(a._)}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8934);function o(){return(0,r.useContext)(a._)}},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});function r(e){const t={};return function e(n,r){Object.entries(n).forEach((n=>{let[a,o]=n;const i=r?`${r}.${a}`:a;var s;"object"==typeof(s=o)&&s&&Object.keys(s).length>0?e(o,i):t[i]=o}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,z:()=>o});var r=n(7294);const a=r.createContext(null);function o(e){let{children:t,value:n}=e;const o=r.useContext(a),i=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...null==n?void 0:n.data};return{plugin:t.plugin,data:r}}({parent:o,value:n})),[o,n]);return r.createElement(a.Provider,{value:i},t)}},143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>g,gA:()=>p,WS:()=>m,_r:()=>d,Jo:()=>v,zh:()=>f,yW:()=>b,gB:()=>h});var r=n(6550),a=n(2263),o=n(9935);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,a.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const s=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=s(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.LX)(t,{path:e.path,exact:!1,strict:!1})))}function c(e,t){const n=l(e,t),a=null==n?void 0:n.docs.find((e=>!!(0,r.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:a,alternateDocVersions:a?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(a.id):{}}}const u={},d=()=>i("docusaurus-plugin-content-docs")??u,f=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const r=i(e),a=null==r?void 0:r[t];if(!a&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return a}("docusaurus-plugin-content-docs",e,{failfast:!0});function p(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,r.TH)();return function(e,t,n){void 0===n&&(n={});const a=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=a?{pluginId:a[0],pluginData:a[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function m(e){void 0===e&&(e={});const t=p(e),{pathname:n}=(0,r.TH)();if(!t)return;return{activePlugin:t,activeVersion:l(t.pluginData,n)}}function h(e){return f(e).versions}function b(e){const t=f(e);return s(t)}function g(e){const t=f(e),{pathname:n}=(0,r.TH)();return c(t,n)}function v(e){const t=f(e),{pathname:n}=(0,r.TH)();return function(e,t){const n=s(e);return{latestDocSuggestion:c(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(4865),a=n.n(r);a().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{a().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){a().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var r=n(7410),a=n(6809);!function(e){const{themeConfig:{prism:t}}=a.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{n(6726)(`./prism-${e}`)})),delete globalThis.Prism}(r.Z)},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294);const a="iconExternalLink_nPIU";function o(e){let{width:t=13.5,height:n=13.5}=e;return r.createElement("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:a},r.createElement("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"}))}},9889:(e,t,n)=>{"use strict";n.d(t,{Z:()=>Pt});var r=n(7294),a=n(6010),o=n(4763),i=n(833),s=n(7462),l=n(6550),c=n(5999),u=n(5936);const d="docusaurus_skipToContent_fallback";function f(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function p(){const e=(0,r.useRef)(null),{action:t}=(0,l.k6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&f(t)}),[]);return(0,u.S)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&f(e.current)})),{containerRef:e,onClick:n}}const m=(0,c.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function h(e){const t=e.children??m,{containerRef:n,onClick:a}=p();return r.createElement("div",{ref:n,role:"region","aria-label":m},r.createElement("a",(0,s.Z)({},e,{href:`#${d}`,onClick:a}),t))}var b=n(5281),g=n(9727);const v="skipToContent_fXgn";function y(){return r.createElement(h,{className:v})}var w=n(6668),S=n(9689);function k(e){let{width:t=21,height:n=21,color:a="currentColor",strokeWidth:o=1.2,className:i,...l}=e;return r.createElement("svg",(0,s.Z)({viewBox:"0 0 15 15",width:t,height:n},l),r.createElement("g",{stroke:a,strokeWidth:o},r.createElement("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})))}const E="closeButton_CVFx";function x(e){return r.createElement("button",(0,s.Z)({type:"button","aria-label":(0,c.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"})},e,{className:(0,a.Z)("clean-btn close",E,e.className)}),r.createElement(k,{width:14,height:14,strokeWidth:3.1}))}const _="content_knG7";function C(e){const{announcementBar:t}=(0,w.L)(),{content:n}=t;return r.createElement("div",(0,s.Z)({},e,{className:(0,a.Z)(_,e.className),dangerouslySetInnerHTML:{__html:n}}))}const T="announcementBar_mb4j",A="announcementBarPlaceholder_vyr4",P="announcementBarClose_gvF7",O="announcementBarContent_xLdY";function R(){const{announcementBar:e}=(0,w.L)(),{isActive:t,close:n}=(0,S.nT)();if(!t)return null;const{backgroundColor:a,textColor:o,isCloseable:i}=e;return r.createElement("div",{className:T,style:{backgroundColor:a,color:o},role:"banner"},i&&r.createElement("div",{className:A}),r.createElement(C,{className:O}),i&&r.createElement(x,{onClick:n,className:P}))}var L=n(2961),I=n(2466);var N=n(902),D=n(3102);const M=r.createContext(null);function B(e){let{children:t}=e;const n=function(){const e=(0,L.e)(),t=(0,D.HY)(),[n,a]=(0,r.useState)(!1),o=null!==t.component,i=(0,N.D9)(o);return(0,r.useEffect)((()=>{o&&!i&&a(!0)}),[o,i]),(0,r.useEffect)((()=>{o?e.shown||a(!0):a(!1)}),[e.shown,o]),(0,r.useMemo)((()=>[n,a]),[n])}();return r.createElement(M.Provider,{value:n},t)}function F(e){if(e.component){const t=e.component;return r.createElement(t,e.props)}}function j(){const e=(0,r.useContext)(M);if(!e)throw new N.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,a=(0,r.useCallback)((()=>n(!1)),[n]),o=(0,D.HY)();return(0,r.useMemo)((()=>({shown:t,hide:a,content:F(o)})),[a,o,t])}function U(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:i}=j();return r.createElement("div",{className:"navbar-sidebar"},t,r.createElement("div",{className:(0,a.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":i})},r.createElement("div",{className:"navbar-sidebar__item menu"},n),r.createElement("div",{className:"navbar-sidebar__item menu"},o)))}var z=n(2949),$=n(2389);function H(e){return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"}))}function q(e){return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"}))}const G={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function Z(e){let{className:t,value:n,onChange:o}=e;const i=(0,$.Z)(),s=(0,c.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===n?(0,c.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return r.createElement("div",{className:(0,a.Z)(G.toggle,t)},r.createElement("button",{className:(0,a.Z)("clean-btn",G.toggleButton,!i&&G.toggleButtonDisabled),type:"button",onClick:()=>o("dark"===n?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite"},r.createElement(H,{className:(0,a.Z)(G.toggleIcon,G.lightToggleIcon)}),r.createElement(q,{className:(0,a.Z)(G.toggleIcon,G.darkToggleIcon)})))}const V=r.memo(Z);function W(e){let{className:t}=e;const n=(0,w.L)().colorMode.disableSwitch,{colorMode:a,setColorMode:o}=(0,z.I)();return n?null:r.createElement(V,{className:t,value:a,onChange:o})}var K=n(1327);function Y(){return r.createElement(K.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Q(){const e=(0,L.e)();return r.createElement("button",{type:"button","aria-label":(0,c.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle()},r.createElement(k,{color:"var(--ifm-color-emphasis-600)"}))}function X(){return r.createElement("div",{className:"navbar-sidebar__brand"},r.createElement(Y,null),r.createElement(W,{className:"margin-right--md"}),r.createElement(Q,null))}var J=n(9960),ee=n(4996),te=n(3919),ne=n(8022),re=n(9471);function ae(e){let{activeBasePath:t,activeBaseRegex:n,to:a,href:o,label:i,html:l,isDropdownLink:c,prependBaseUrlToHref:u,...d}=e;const f=(0,ee.Z)(a),p=(0,ee.Z)(t),m=(0,ee.Z)(o,{forcePrependBaseUrl:!0}),h=i&&o&&!(0,te.Z)(o),b=l?{dangerouslySetInnerHTML:{__html:l}}:{children:r.createElement(r.Fragment,null,i,h&&r.createElement(re.Z,c&&{width:12,height:12}))};return o?r.createElement(J.Z,(0,s.Z)({href:u?m:o},d,b)):r.createElement(J.Z,(0,s.Z)({to:f,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?(0,ne.F)(n,t.pathname):t.pathname.startsWith(p)},d,b))}function oe(e){let{className:t,isDropdownItem:n=!1,...o}=e;const i=r.createElement(ae,(0,s.Z)({className:(0,a.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},o));return n?r.createElement("li",null,i):i}function ie(e){let{className:t,isDropdownItem:n,...o}=e;return r.createElement("li",{className:"menu__list-item"},r.createElement(ae,(0,s.Z)({className:(0,a.Z)("menu__link",t)},o)))}function se(e){let{mobile:t=!1,position:n,...a}=e;const o=t?ie:oe;return r.createElement(o,(0,s.Z)({},a,{activeClassName:a.activeClassName??(t?"menu__link--active":"navbar__link--active")}))}var le=n(6043),ce=n(8596),ue=n(2263);function de(e,t){return e.some((e=>function(e,t){return!!(0,ce.Mg)(e.to,t)||!!(0,ne.F)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function fe(e){let{items:t,position:n,className:o,onClick:i,...l}=e;const c=(0,r.useRef)(null),[u,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{c.current&&!c.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e)}}),[c]),r.createElement("div",{ref:c,className:(0,a.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":u})},r.createElement(ae,(0,s.Z)({"aria-haspopup":"true","aria-expanded":u,role:"button",href:l.to?void 0:"#",className:(0,a.Z)("navbar__link",o)},l,{onClick:l.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!u))}}),l.children??l.label),r.createElement("ul",{className:"dropdown__menu"},t.map(((e,n)=>r.createElement(qe,(0,s.Z)({isDropdownItem:!0,onKeyDown:e=>{if(n===t.length-1&&"Tab"===e.key){e.preventDefault(),d(!1);const t=c.current.nextElementSibling;if(t){(t instanceof HTMLAnchorElement?t:t.querySelector("a")).focus()}}},activeClassName:"dropdown__link--active"},e,{key:n}))))))}function pe(e){let{items:t,className:n,position:o,onClick:i,...c}=e;const u=function(){const{siteConfig:{baseUrl:e}}=(0,ue.Z)(),{pathname:t}=(0,l.TH)();return t.replace(e,"/")}(),d=de(t,u),{collapsed:f,toggleCollapsed:p,setCollapsed:m}=(0,le.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[u,d,m]),r.createElement("li",{className:(0,a.Z)("menu__list-item",{"menu__list-item--collapsed":f})},r.createElement(ae,(0,s.Z)({role:"button",className:(0,a.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n)},c,{onClick:e=>{e.preventDefault(),p()}}),c.children??c.label),r.createElement(le.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:f},t.map(((e,t)=>r.createElement(qe,(0,s.Z)({mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active"},e,{key:t}))))))}function me(e){let{mobile:t=!1,...n}=e;const a=t?pe:fe;return r.createElement(a,n)}var he=n(4711);function be(e){let{width:t=20,height:n=20,...a}=e;return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},a),r.createElement("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"}))}const ge="iconLanguage_nlXk";var ve=n(3935),ye=n(5742),we=n(6177);function Se(){return r.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},r.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}var ke=n(830),Ee=["translations"];function xe(){return xe=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var Ae="Ctrl";var Pe=r.forwardRef((function(e,t){var n=e.translations,a=void 0===n?{}:n,o=Te(e,Ee),i=a.buttonText,s=void 0===i?"Search":i,l=a.buttonAriaLabel,c=void 0===l?"Search":l,u=_e((0,r.useState)(null),2),d=u[0],f=u[1];return(0,r.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?f("\u2318"):f(Ae))}),[]),r.createElement("button",xe({type:"button",className:"DocSearch DocSearch-Button","aria-label":c},o,{ref:t}),r.createElement("span",{className:"DocSearch-Button-Container"},r.createElement(ke.W,null),r.createElement("span",{className:"DocSearch-Button-Placeholder"},s)),r.createElement("span",{className:"DocSearch-Button-Keys"},null!==d&&r.createElement(r.Fragment,null,r.createElement("kbd",{className:"DocSearch-Button-Key"},d===Ae?r.createElement(Se,null):d),r.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))})),Oe=n(3320);const Re={button:{buttonText:(0,c.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,c.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,c.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,c.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,c.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,c.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,c.I)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,c.I)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,c.I)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,c.I)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,c.I)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,c.I)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,c.I)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,c.I)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,c.I)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,c.I)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let Le=null;function Ie(e){let{hit:t,children:n}=e;return r.createElement(J.Z,{to:t.url},n)}function Ne(e){let{state:t,onClose:n}=e;const{generateSearchPageLink:a}=(0,we.O)();return r.createElement(J.Z,{to:a(t.query),onClick:n},r.createElement(c.Z,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits}},"See all {count} results"))}function De(e){var t;let{contextualSearch:a,externalUrlRegex:o,...i}=e;const{siteMetadata:c}=(0,ue.Z)(),u=function(){const{locale:e,tags:t}=(0,Oe._q)();return[`language:${e}`,t.map((e=>`docusaurus_tag:${e}`))]}(),d=(null==(t=i.searchParameters)?void 0:t.facetFilters)??[],f=a?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(u,d):d,p={...i.searchParameters,facetFilters:f},{withBaseUrl:m}=(0,ee.C)(),h=(0,l.k6)(),b=(0,r.useRef)(null),g=(0,r.useRef)(null),[v,y]=(0,r.useState)(!1),[w,S]=(0,r.useState)(void 0),k=(0,r.useCallback)((()=>Le?Promise.resolve():Promise.all([n.e(6780).then(n.bind(n,6780)),Promise.all([n.e(532),n.e(6945)]).then(n.bind(n,6945)),Promise.all([n.e(532),n.e(8894)]).then(n.bind(n,8894))]).then((e=>{let[{DocSearchModal:t}]=e;Le=t}))),[]),E=(0,r.useCallback)((()=>{k().then((()=>{b.current=document.createElement("div"),document.body.insertBefore(b.current,document.body.firstChild),y(!0)}))}),[k,y]),x=(0,r.useCallback)((()=>{var e;y(!1),null==(e=b.current)||e.remove()}),[y]),_=(0,r.useCallback)((e=>{k().then((()=>{y(!0),S(e.key)}))}),[k,y,S]),C=(0,r.useRef)({navigate(e){let{itemUrl:t}=e;(0,ne.F)(o,t)?window.location.href=t:h.push(t)}}).current,T=(0,r.useRef)((e=>e.map((e=>{if((0,ne.F)(o,e.url))return e;const t=new URL(e.url);return{...e,url:m(`${t.pathname}${t.hash}`)}})))).current,A=(0,r.useMemo)((()=>e=>r.createElement(Ne,(0,s.Z)({},e,{onClose:x}))),[x]),P=(0,r.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",c.docusaurusVersion),e)),[c.docusaurusVersion]);return function(e){var t=e.isOpen,n=e.onOpen,a=e.onClose,o=e.onInput,i=e.searchButtonRef;r.useEffect((function(){function e(e){(27===e.keyCode&&t||"k"===e.key.toLowerCase()&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)&&(e.preventDefault(),t?a():document.body.classList.contains("DocSearch--active")||document.body.classList.contains("DocSearch--active")||n()),i&&i.current===document.activeElement&&o&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&o(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,a,o,i])}({isOpen:v,onOpen:E,onClose:x,onInput:_,searchButtonRef:g}),r.createElement(r.Fragment,null,r.createElement(ye.Z,null,r.createElement("link",{rel:"preconnect",href:`https://${i.appId}-dsn.algolia.net`,crossOrigin:"anonymous"})),r.createElement(Pe,{onTouchStart:k,onFocus:k,onMouseOver:k,onClick:E,ref:g,translations:Re.button}),v&&Le&&b.current&&(0,ve.createPortal)(r.createElement(Le,(0,s.Z)({onClose:x,initialScrollY:window.scrollY,initialQuery:w,navigator:C,transformItems:T,hitComponent:Ie,transformSearchClient:P},i.searchPagePath&&{resultsFooterComponent:A},i,{searchParameters:p,placeholder:Re.placeholder,translations:Re.modal})),b.current))}function Me(){const{siteConfig:e}=(0,ue.Z)();return r.createElement(De,e.themeConfig.algolia)}const Be="searchBox_ZlJk";function Fe(e){let{children:t,className:n}=e;return r.createElement("div",{className:(0,a.Z)(n,Be)},t)}var je=n(143),Ue=n(2802);var ze=n(373);const $e=e=>e.docs.find((t=>t.id===e.mainDocId));const He={default:se,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:a,...o}=e;const{i18n:{currentLocale:i,locales:u,localeConfigs:d}}=(0,ue.Z)(),f=(0,he.l)(),{search:p,hash:m}=(0,l.TH)(),h=[...n,...u.map((e=>{const n=`${`pathname://${f.createUrl({locale:e,fullyQualified:!1})}`}${p}${m}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...a],b=t?(0,c.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return r.createElement(me,(0,s.Z)({},o,{mobile:t,label:r.createElement(r.Fragment,null,r.createElement(be,{className:ge}),b),items:h}))},search:function(e){let{mobile:t,className:n}=e;return t?null:r.createElement(Fe,{className:n},r.createElement(Me,null))},dropdown:me,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:i=!1}=e;const s=i?"li":"div";return r.createElement(s,{className:(0,a.Z)({navbar__item:!o&&!i,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,je.Iw)(a),l=(0,Ue.vY)(t,a);return null===l?null:r.createElement(se,(0,s.Z)({exact:!0},o,{isActive:()=>(null==i?void 0:i.path)===l.path||!(null==i||!i.sidebar)&&i.sidebar===l.sidebar,label:n??l.id,to:l.path}))},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,je.Iw)(a),l=(0,Ue.oz)(t,a).link;if(!l)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return r.createElement(se,(0,s.Z)({exact:!0},o,{isActive:()=>(null==i?void 0:i.sidebar)===t,label:n??l.label,to:l.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:a,...o}=e;const i=(0,Ue.lO)(a)[0],l=t??i.label,c=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(i).path;return r.createElement(se,(0,s.Z)({},o,{label:l,to:c}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:a,dropdownItemsBefore:o,dropdownItemsAfter:i,...u}=e;const{search:d,hash:f}=(0,l.TH)(),p=(0,je.Iw)(n),m=(0,je.gB)(n),{savePreferredVersionName:h}=(0,ze.J)(n),b=[...o,...m.map((e=>{const t=p.alternateDocVersions[e.name]??$e(e);return{label:e.label,to:`${t.path}${d}${f}`,isActive:()=>e===p.activeVersion,onClick:()=>h(e.name)}})),...i],g=(0,Ue.lO)(n)[0],v=t&&b.length>1?(0,c.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):g.label,y=t&&b.length>1?void 0:$e(g).path;return b.length<=1?r.createElement(se,(0,s.Z)({},u,{mobile:t,label:v,to:y,isActive:a?()=>!1:void 0})):r.createElement(me,(0,s.Z)({},u,{mobile:t,label:v,to:y,items:b,isActive:a?()=>!1:void 0}))}};function qe(e){let{type:t,...n}=e;const a=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=He[a];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return r.createElement(o,n)}function Ge(){const e=(0,L.e)(),t=(0,w.L)().navbar.items;return r.createElement("ul",{className:"menu__list"},t.map(((t,n)=>r.createElement(qe,(0,s.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function Ze(e){return r.createElement("button",(0,s.Z)({},e,{type:"button",className:"clean-btn navbar-sidebar__back"}),r.createElement(c.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"},"\u2190 Back to main menu"))}function Ve(){const e=0===(0,w.L)().navbar.items.length,t=j();return r.createElement(r.Fragment,null,!e&&r.createElement(Ze,{onClick:()=>t.hide()}),t.content)}function We(){const e=(0,L.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?r.createElement(U,{header:r.createElement(X,null),primaryMenu:r.createElement(Ge,null),secondaryMenu:r.createElement(Ve,null)}):null}const Ke="navbarHideable_m1mJ",Ye="navbarHidden_jGov";function Qe(e){return r.createElement("div",(0,s.Z)({role:"presentation"},e,{className:(0,a.Z)("navbar-sidebar__backdrop",e.className)}))}function Xe(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,w.L)(),i=(0,L.e)(),{navbarRef:s,isNavbarVisible:l}=function(e){const[t,n]=(0,r.useState)(e),a=(0,r.useRef)(!1),o=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,I.RF)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i=s?n(!1):i+c{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return a.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return r.createElement("nav",{ref:s,className:(0,a.Z)("navbar","navbar--fixed-top",n&&[Ke,!l&&Ye],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown})},t,r.createElement(Qe,{onClick:i.toggle}),r.createElement(We,null))}function Je(e){let{width:t=30,height:n=30,className:a,...o}=e;return r.createElement("svg",(0,s.Z)({className:a,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},o),r.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function et(){const{toggle:e,shown:t}=(0,L.e)();return r.createElement("button",{onClick:e,"aria-label":(0,c.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button"},r.createElement(Je,null))}const tt="colorModeToggle_DEke";function nt(e){let{items:t}=e;return r.createElement(r.Fragment,null,t.map(((e,t)=>r.createElement(qe,(0,s.Z)({},e,{key:t})))))}function rt(e){let{left:t,right:n}=e;return r.createElement("div",{className:"navbar__inner"},r.createElement("div",{className:"navbar__items"},t),r.createElement("div",{className:"navbar__items navbar__items--right"},n))}function at(){const e=(0,L.e)(),t=(0,w.L)().navbar.items,[n,a]=function(e){function t(e){return"left"===(e.position??"right")}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return r.createElement(rt,{left:r.createElement(r.Fragment,null,!e.disabled&&r.createElement(et,null),r.createElement(Y,null),r.createElement(nt,{items:n})),right:r.createElement(r.Fragment,null,r.createElement(nt,{items:a}),r.createElement(W,{className:tt}),!o&&r.createElement(Fe,null,r.createElement(Me,null)))})}function ot(){return r.createElement(Xe,null,r.createElement(at,null))}function it(e){let{item:t}=e;const{to:n,href:a,label:o,prependBaseUrlToHref:i,...l}=t,c=(0,ee.Z)(n),u=(0,ee.Z)(a,{forcePrependBaseUrl:!0});return r.createElement(J.Z,(0,s.Z)({className:"footer__link-item"},a?{href:i?u:a}:{to:c},l),o,a&&!(0,te.Z)(a)&&r.createElement(re.Z,null))}function st(e){let{item:t}=e;return t.html?r.createElement("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement("li",{key:t.href??t.to,className:"footer__item"},r.createElement(it,{item:t}))}function lt(e){let{column:t}=e;return r.createElement("div",{className:"col footer__col"},r.createElement("div",{className:"footer__title"},t.title),r.createElement("ul",{className:"footer__items clean-list"},t.items.map(((e,t)=>r.createElement(st,{key:t,item:e})))))}function ct(e){let{columns:t}=e;return r.createElement("div",{className:"row footer__links"},t.map(((e,t)=>r.createElement(lt,{key:t,column:e}))))}function ut(){return r.createElement("span",{className:"footer__link-separator"},"\xb7")}function dt(e){let{item:t}=e;return t.html?r.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement(it,{item:t})}function ft(e){let{links:t}=e;return r.createElement("div",{className:"footer__links text--center"},r.createElement("div",{className:"footer__links"},t.map(((e,n)=>r.createElement(r.Fragment,{key:n},r.createElement(dt,{item:e}),t.length!==n+1&&r.createElement(ut,null))))))}function pt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?r.createElement(ct,{columns:t}):r.createElement(ft,{links:t})}var mt=n(941);const ht="footerLogoLink_BH7S";function bt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,ee.C)(),o={light:n(t.src),dark:n(t.srcDark??t.src)};return r.createElement(mt.Z,{className:(0,a.Z)("footer__logo",t.className),alt:t.alt,sources:o,width:t.width,height:t.height,style:t.style})}function gt(e){let{logo:t}=e;return t.href?r.createElement(J.Z,{href:t.href,className:ht,target:t.target},r.createElement(bt,{logo:t})):r.createElement(bt,{logo:t})}function vt(e){let{copyright:t}=e;return r.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function yt(e){let{style:t,links:n,logo:o,copyright:i}=e;return r.createElement("footer",{className:(0,a.Z)("footer",{"footer--dark":"dark"===t})},r.createElement("div",{className:"container container-fluid"},n,(o||i)&&r.createElement("div",{className:"footer__bottom text--center"},o&&r.createElement("div",{className:"margin-bottom--sm"},o),i)))}function wt(){const{footer:e}=(0,w.L)();if(!e)return null;const{copyright:t,links:n,logo:a,style:o}=e;return r.createElement(yt,{style:o,links:n&&n.length>0&&r.createElement(pt,{links:n}),logo:a&&r.createElement(gt,{logo:a}),copyright:t&&r.createElement(vt,{copyright:t})})}const St=r.memo(wt);var kt=n(12);const Et="docusaurus.tab.",xt=r.createContext(void 0);const _t=(0,N.Qc)([z.S,S.pl,function(e){let{children:t}=e;const n=function(){const[e,t]=(0,r.useState)({}),n=(0,r.useCallback)(((e,t)=>{(0,kt.W)(`docusaurus.tab.${e}`).set(t)}),[]);(0,r.useEffect)((()=>{try{const e={};(0,kt._)().forEach((t=>{if(t.startsWith(Et)){const n=t.substring(Et.length);e[n]=(0,kt.W)(t).get()}})),t(e)}catch(e){console.error(e)}}),[]);const a=(0,r.useCallback)(((e,r)=>{t((t=>({...t,[e]:r}))),n(e,r)}),[n]);return(0,r.useMemo)((()=>({tabGroupChoices:e,setTabGroupChoices:a})),[e,a])}();return r.createElement(xt.Provider,{value:n},t)},I.OC,ze.L5,i.VC,function(e){let{children:t}=e;return r.createElement(D.n2,null,r.createElement(L.M,null,r.createElement(B,null,t)))}]);function Ct(e){let{children:t}=e;return r.createElement(_t,null,t)}function Tt(e){let{error:t,tryAgain:n}=e;return r.createElement("main",{className:"container margin-vert--xl"},r.createElement("div",{className:"row"},r.createElement("div",{className:"col col--6 col--offset-3"},r.createElement("h1",{className:"hero__title"},r.createElement(c.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed"},"This page crashed.")),r.createElement("p",null,t.message),r.createElement("div",null,r.createElement("button",{type:"button",onClick:n},r.createElement(c.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again when the page crashed"},"Try again"))))))}const At="mainWrapper_z2l0";function Pt(e){const{children:t,noFooter:n,wrapperClassName:s,title:l,description:c}=e;return(0,g.t)(),r.createElement(Ct,null,r.createElement(i.d,{title:l,description:c}),r.createElement(y,null),r.createElement(R,null),r.createElement(ot,null),r.createElement("div",{id:d,className:(0,a.Z)(b.k.wrapper.main,At,s)},r.createElement(o.Z,{fallback:e=>r.createElement(Tt,e)},t)),!n&&r.createElement(St,null))}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var r=n(7462),a=n(7294),o=n(9960),i=n(4996),s=n(2263),l=n(6668),c=n(941);function u(e){let{logo:t,alt:n,imageClassName:r}=e;const o={light:(0,i.Z)(t.src),dark:(0,i.Z)(t.srcDark||t.src)},s=a.createElement(c.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return r?a.createElement("div",{className:r},s):s}function d(e){const{siteConfig:{title:t}}=(0,s.Z)(),{navbar:{title:n,logo:c}}=(0,l.L)(),{imageClassName:d,titleClassName:f,...p}=e,m=(0,i.Z)((null==c?void 0:c.href)||"/"),h=n?"":t,b=(null==c?void 0:c.alt)??h;return a.createElement(o.Z,(0,r.Z)({to:m},p,(null==c?void 0:c.target)&&{target:c.target}),c&&a.createElement(u,{logo:c,alt:b,imageClassName:d}),null!=n&&a.createElement("b",{className:f},n))}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(5742);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return r.createElement(a.Z,null,t&&r.createElement("meta",{name:"docusaurus_locale",content:t}),n&&r.createElement("meta",{name:"docusaurus_version",content:n}),o&&r.createElement("meta",{name:"docusaurus_tag",content:o}),i&&r.createElement("meta",{name:"docsearch:language",content:i}),n&&r.createElement("meta",{name:"docsearch:version",content:n}),o&&r.createElement("meta",{name:"docsearch:docusaurus_tag",content:o}))}},941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var r=n(7462),a=n(7294),o=n(6010),i=n(2389),s=n(2949);const l={themedImage:"themedImage_ToTc","themedImage--light":"themedImage--light_HNdA","themedImage--dark":"themedImage--dark_i4oU"};function c(e){const t=(0,i.Z)(),{colorMode:n}=(0,s.I)(),{sources:c,className:u,alt:d,...f}=e,p=t?"dark"===n?["dark"]:["light"]:["light","dark"];return a.createElement(a.Fragment,null,p.map((e=>a.createElement("img",(0,r.Z)({key:e,src:c[e],alt:d,className:(0,o.Z)(l.themedImage,l[`themedImage--${e}`],u)},f)))))}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>i,z:()=>m});var r=n(7462),a=n(7294),o=n(412);function i(e){let{initialState:t}=e;const[n,r]=(0,a.useState)(t??!1),o=(0,a.useCallback)((()=>{r((e=>!e))}),[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:o}}const s={display:"none",overflow:"hidden",height:"0px"},l={display:"block",overflow:"visible",height:"auto"};function c(e,t){const n=t?s:l;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function u(e){let{collapsibleRef:t,collapsed:n,animation:r}=e;const o=(0,a.useRef)(!1);(0,a.useEffect)((()=>{const e=t.current;function a(){const t=e.scrollHeight,n=(null==r?void 0:r.duration)??function(e){const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${(null==r?void 0:r.easing)??"ease-in-out"}`,height:`${t}px`}}function i(){const t=a();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return c(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(i(),requestAnimationFrame((()=>{e.style.height=s.height,e.style.overflow=s.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{i()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,r])}function d(e){if(!o.Z.canUseDOM)return e?s:l}function f(e){let{as:t="div",collapsed:n,children:r,animation:o,onCollapseTransitionEnd:i,className:s,disableSSRStyle:l}=e;const f=(0,a.useRef)(null);return u({collapsibleRef:f,collapsed:n,animation:o}),a.createElement(t,{ref:f,style:l?void 0:d(n),onTransitionEnd:e=>{"height"===e.propertyName&&(c(f.current,n),null==i||i(n))},className:s},r)}function p(e){let{collapsed:t,...n}=e;const[o,i]=(0,a.useState)(!t),[s,l]=(0,a.useState)(t);return(0,a.useLayoutEffect)((()=>{t||i(!0)}),[t]),(0,a.useLayoutEffect)((()=>{o&&l(t)}),[o,t]),o?a.createElement(f,(0,r.Z)({},n,{collapsed:s})):null}function m(e){let{lazy:t,...n}=e;const r=t?p:f;return a.createElement(r,n)}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>m,pl:()=>p});var r=n(7294),a=n(2389),o=n(12),i=n(902),s=n(6668);const l=(0,o.W)("docusaurus.announcement.dismiss"),c=(0,o.W)("docusaurus.announcement.id"),u=()=>"true"===l.get(),d=e=>l.set(String(e)),f=r.createContext(null);function p(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.L)(),t=(0,a.Z)(),[n,o]=(0,r.useState)((()=>!!t&&u()));(0,r.useEffect)((()=>{o(u())}),[]);const i=(0,r.useCallback)((()=>{d(!0),o(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=c.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;c.set(t),r&&d(!1),!r&&u()||o(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return r.createElement(f.Provider,{value:n},t)}function m(){const e=(0,r.useContext)(f);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>b,S:()=>h});var r=n(7294),a=n(412),o=n(902),i=n(12),s=n(6668);const l=r.createContext(void 0),c="theme",u=(0,i.W)(c),d="light",f="dark",p=e=>e===f?f:d;function m(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.L)(),[o,i]=(0,r.useState)((e=>a.Z.canUseDOM?p(document.documentElement.getAttribute("data-theme")):p(e))(e));(0,r.useEffect)((()=>{t&&u.del()}),[t]);const l=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:a=!0}=r;t?(i(t),a&&(e=>{u.set(p(e))})(t)):(i(n?window.matchMedia("(prefers-color-scheme: dark)").matches?f:d:e),u.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",p(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==c)return;const t=u.get();null!==t&&l(p(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,l]);const m=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||m.current?m.current=window.matchMedia("print").matches:l(null)};return e.addListener(r),()=>e.removeListener(r)}),[l,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:l,get isDarkTheme(){return o===f},setLightTheme(){l(d)},setDarkTheme(){l(f)}})),[o,l])}function h(e){let{children:t}=e;const n=m();return r.createElement(l.Provider,{value:n},t)}function b(){const e=(0,r.useContext)(l);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},373:(e,t,n)=>{"use strict";n.d(t,{J:()=>y,L5:()=>g,Oh:()=>w});var r=n(7294),a=n(143),o=n(9935),i=n(6668),s=n(2802),l=n(902),c=n(12);const u=e=>`docs-preferred-version-${e}`,d=(e,t,n)=>{(0,c.W)(u(e),{persistence:t}).set(n)},f=(e,t)=>(0,c.W)(u(e),{persistence:t}).get(),p=(e,t)=>{(0,c.W)(u(e),{persistence:t}).del()};const m=r.createContext(null);function h(){const e=(0,a._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[o,s]=(0,r.useState)((()=>(e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}]))))(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function a(e){const t=f(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,a(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function b(e){let{children:t}=e;const n=h();return r.createElement(m.Provider,{value:n},t)}function g(e){let{children:t}=e;return s.cE?r.createElement(b,null,t):r.createElement(r.Fragment,null,t)}function v(){const e=(0,r.useContext)(m);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function y(e){void 0===e&&(e=o.m);const t=(0,a.zh)(e),[n,i]=v(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}function w(){const e=(0,a._r)(),[t]=v();function n(n){const r=e[n],{preferredVersionName:a}=t[n];return r.versions.find((e=>e.name===a))??null}const r=Object.keys(e);return Object.fromEntries(r.map((e=>[e,n(e)])))}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,b:()=>s});var r=n(7294),a=n(902);const o=Symbol("EmptyContext"),i=r.createContext(o);function s(e){let{children:t,name:n,items:a}=e;const o=(0,r.useMemo)((()=>n&&a?{name:n,items:a}:null),[n,a]);return r.createElement(i.Provider,{value:o},t)}function l(){const e=(0,r.useContext)(i);if(e===o)throw new a.i6("DocsSidebarProvider");return e}},4477:(e,t,n)=>{"use strict";n.d(t,{E:()=>s,q:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t,version:n}=e;return r.createElement(o.Provider,{value:n},t)}function s(){const e=(0,r.useContext)(o);if(null===e)throw new a.i6("DocsVersionProvider");return e}},2961:(e,t,n)=>{"use strict";n.d(t,{M:()=>f,e:()=>p});var r=n(7294),a=n(3102),o=n(7524),i=n(6550),s=n(902);function l(e){!function(e){const t=(0,i.k6)(),n=(0,s.zX)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}var c=n(6668);const u=r.createContext(void 0);function d(){const e=function(){const e=(0,a.HY)(),{items:t}=(0,c.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[i,s]=(0,r.useState)(!1);l((()=>{if(i)return s(!1),!1}));const u=(0,r.useCallback)((()=>{s((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&s(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:i})),[e,n,u,i])}function f(e){let{children:t}=e;const n=d();return r.createElement(u.Provider,{value:n},t)}function p(){const e=r.useContext(u);if(void 0===e)throw new s.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>s,Zo:()=>l,n2:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return r.createElement(o.Provider,{value:n},t)}function s(){const e=(0,r.useContext)(o);if(!e)throw new a.i6("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const i=(0,r.useContext)(o);if(!i)throw new a.i6("NavbarSecondaryMenuContentProvider");const[,s]=i,l=(0,a.Ql)(n);return(0,r.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>a,t:()=>o});var r=n(7294);const a="navigation-with-keyboard";function o(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(a),"mousedown"===e.type&&document.body.classList.remove(a)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(a),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},6177:(e,t,n)=>{"use strict";n.d(t,{O:()=>s});var r=n(7294),a=n(6550),o=n(2263);const i="q";function s(){const e=(0,a.k6)(),{siteConfig:{baseUrl:t}}=(0,o.Z)(),[n,s]=(0,r.useState)("");(0,r.useEffect)((()=>{const e=new URLSearchParams(window.location.search).get(i)??"";s(e)}),[]);return{searchQuery:n,setSearchQuery:(0,r.useCallback)((t=>{const n=new URLSearchParams(window.location.search);t?n.set(i,t):n.delete(i),e.replace({search:n.toString()}),s(t)}),[e]),generateSearchPageLink:(0,r.useCallback)((e=>`${t}search?q=${encodeURIComponent(e)}`),[t])}}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>c});var r=n(7294),a=n(412);const o="desktop",i="mobile",s="ssr";function l(){return a.Z.canUseDOM?window.innerWidth>996?o:i:s}function c(){const[e,t]=(0,r.useState)((()=>l()));return(0,r.useEffect)((()=>{function e(){t(l())}return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),clearTimeout(undefined)}}),[]),e}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},2802:(e,t,n)=>{"use strict";n.d(t,{MN:()=>x,Wl:()=>m,_F:()=>g,cE:()=>f,jA:()=>h,xz:()=>p,hI:()=>E,lO:()=>w,vY:()=>k,oz:()=>S,s1:()=>y});var r=n(7294),a=n(6550),o=n(8790),i=n(143),s=n(373),l=n(4477),c=n(1116);function u(e){return Array.from(new Set(e))}var d=n(8596);const f=!!i._r;function p(e){const t=(0,l.E)();if(!e)return;const n=t.docs[e];if(!n)throw new Error(`no version doc found by id=${e}`);return n}function m(e){if(e.href)return e.href;for(const t of e.items){if("link"===t.type)return t.href;if("category"===t.type){const e=m(t);if(e)return e}}}function h(){const{pathname:e}=(0,a.TH)(),t=(0,c.V)();if(!t)throw new Error("Unexpected: cant find current sidebar in context");const n=v({sidebarItems:t.items,pathname:e,onlyCategories:!0}).slice(-1)[0];if(!n)throw new Error(`${e} is not associated with a category. useCurrentSidebarCategory() should only be used on category index pages.`);return n}const b=(e,t)=>void 0!==e&&(0,d.Mg)(e,t);function g(e,t){return"link"===e.type?b(e.href,t):"category"===e.type&&(b(e.href,t)||((e,t)=>e.some((e=>g(e,t))))(e.items,t))}function v(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const a=[];return function e(t){for(const o of t)if("category"===o.type&&((0,d.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,d.Mg)(o.href,n)){return r&&"category"!==o.type||a.unshift(o),!0}return!1}(t),a}function y(){var e;const t=(0,c.V)(),{pathname:n}=(0,a.TH)();return!1!==(null==(e=(0,i.gA)())?void 0:e.pluginData.breadcrumbs)&&t?v({sidebarItems:t.items,pathname:n}):null}function w(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,s.J)(e),a=(0,i.yW)(e);return(0,r.useMemo)((()=>u([t,n,a].filter(Boolean))),[t,n,a])}function S(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\n Available sidebar ids are:\n - ${Object.keys(t).join("\n- ")}`);return r[1]}),[e,n])}function k(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`DocNavbarItem: couldn't find any doc with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${u(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function E(e){let{route:t,versionMetadata:n}=e;const r=(0,a.TH)(),i=t.routes,s=i.find((e=>(0,a.LX)(r.pathname,e)));if(!s)return null;const l=s.sidebar,c=l?n.docsSidebars[l]:void 0;return{docElement:(0,o.H)(i),sidebarName:l,sidebarItems:c}}function x(e){return e.filter((e=>"category"!==e.type||!!m(e)))}},2128:(e,t,n)=>{"use strict";n.d(t,{p:()=>a});var r=n(2263);function a(e){const{siteConfig:t}=(0,r.Z)(),{title:n,titleDelimiter:a}=t;return null!=e&&e.trim().length?`${e.trim()} ${a} ${n}`:n}},833:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>u,VC:()=>p});var r=n(7294),a=n(6010),o=n(5742),i=n(226);function s(){const e=r.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(4996),c=n(2128);function u(e){let{title:t,description:n,keywords:a,image:i,children:s}=e;const u=(0,c.p)(t),{withBaseUrl:d}=(0,l.C)(),f=i?d(i,{absolute:!0}):void 0;return r.createElement(o.Z,null,t&&r.createElement("title",null,u),t&&r.createElement("meta",{property:"og:title",content:u}),n&&r.createElement("meta",{name:"description",content:n}),n&&r.createElement("meta",{property:"og:description",content:n}),a&&r.createElement("meta",{name:"keywords",content:Array.isArray(a)?a.join(","):a}),f&&r.createElement("meta",{property:"og:image",content:f}),f&&r.createElement("meta",{name:"twitter:image",content:f}),s)}const d=r.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=r.useContext(d),s=(0,a.Z)(i,t);return r.createElement(d.Provider,{value:s},r.createElement(o.Z,null,r.createElement("html",{className:s})),n)}function p(e){let{children:t}=e;const n=s(),o=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const i=`plugin-id-${n.plugin.id}`;return r.createElement(f,{className:(0,a.Z)(o,i)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>i,Qc:()=>c,Ql:()=>l,i6:()=>s,zX:()=>o});var r=n(7294);const a=n(412).Z.canUseDOM?r.useLayoutEffect:r.useEffect;function o(e){const t=(0,r.useRef)(e);return a((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function i(e){const t=(0,r.useRef)();return a((()=>{t.current=e})),t.current}class s extends Error{constructor(e,t){var n,r,a;super(),this.name="ReactContextError",this.message=`Hook ${(null==(n=this.stack)||null==(r=n.split("\n")[1])||null==(a=r.match(/at (?:\w+\.)?(?\w+)/))?void 0:a.groups.name)??""} is called outside the <${e}>. ${t??""}`}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function c(e){return t=>{let{children:n}=t;return r.createElement(r.Fragment,null,e.reduceRight(((e,t)=>r.createElement(t,null,e)),n))}}},8022:(e,t,n)=>{"use strict";function r(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{F:()=>r})},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>s});var r=n(7294),a=n(723),o=n(2263);function i(e,t){const n=e=>{var t;return null==(t=!e||e.endsWith("/")?e:`${e}/`)?void 0:t.toLowerCase()};return n(e)===n(t)}function s(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function a(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(a).flatMap((e=>e.routes??[])))}(n)}({routes:a.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>l,RF:()=>d});var r=n(7294),a=n(412),o=n(2389),i=n(902);const s=r.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return r.createElement(s.Provider,{value:n},t)}function c(){const e=(0,r.useContext)(s);if(null==e)throw new i.i6("ScrollControllerProvider");return e}const u=()=>a.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=c(),a=(0,r.useRef)(u()),o=(0,i.zX)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=u();o(e,a.current),a.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function f(){const e=(0,r.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const a=document.documentElement.scrollTop;(n&&a>e||!n&&at&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>null==e.current?void 0:e.current()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>i,_q:()=>l,os:()=>s});var r=n(143),a=n(2263),o=n(373);const i="default";function s(e,t){return`docs-${e}-${t}`}function l(){const{i18n:e}=(0,a.Z)(),t=(0,r._r)(),n=(0,r.WS)(),l=(0,o.Oh)();const c=[i,...Object.keys(t).map((function(e){const r=(null==n?void 0:n.activePlugin.pluginId)===e?n.activeVersion:void 0,a=l[e],o=t[e].versions.find((e=>e.isLast));return s(e,(r??a??o).name)}))];return{locale:e.currentLocale,tags:c}}},12:(e,t,n)=>{"use strict";n.d(t,{W:()=>s,_:()=>l});const r="localStorage";function a(e){if(void 0===e&&(e=r),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,o||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),o=!0),null}var t}let o=!1;const i={get:()=>null,set:()=>{},del:()=>{}};function s(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t}}(e);const n=a(null==t?void 0:t.persistence);return null===n?i:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{n.setItem(e,t)}catch(r){console.error(`Docusaurus storage error, can't set ${e}=${t}`,r)}},del:()=>{try{n.removeItem(e)}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}}}}function l(e){void 0===e&&(e=r);const t=a(e);if(!t)return[];const n=[];for(let r=0;r{"use strict";n.d(t,{l:()=>o});var r=n(2263),a=n(6550);function o(){const{siteConfig:{baseUrl:e,url:t},i18n:{defaultLocale:n,currentLocale:o}}=(0,r.Z)(),{pathname:i}=(0,a.TH)(),s=o===n?e:e.replace(`/${o}/`,"/"),l=i.replace(e,"");return{createUrl:function(e){let{locale:r,fullyQualified:a}=e;return`${a?t:""}${function(e){return e===n?`${s}`:`${s}${e}/`}(r)}${l}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var r=n(7294),a=n(6550),o=n(902);function i(e){const t=(0,a.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){return(0,r.Z)().siteConfig.themeConfig}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[a]=e.split(/[#?]/),o="/"===a||a===r?a:(i=a,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(a,o)}},8780:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="post-content";var a=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(a).default}})},6010:(e,t,n)=>{"use strict";function r(e){var t,n,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;ta});const a=function(){for(var e,t,n=0,a="";n{"use strict";n.d(t,{lX:()=>E,q_:()=>P,ob:()=>h,PP:()=>R,Ep:()=>m,Hp:()=>b});var r=n(7462);function a(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,r=n+1,a=e.length;r=0;f--){var p=i[f];"."===p?o(i,f):".."===p?(o(i,f),d++):d&&(o(i,f),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&a(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};function s(e){return e.valueOf?e.valueOf():Object.prototype.valueOf.call(e)}const l=function e(t,n){if(t===n)return!0;if(null==t||null==n)return!1;if(Array.isArray(t))return Array.isArray(n)&&t.length===n.length&&t.every((function(t,r){return e(t,n[r])}));if("object"==typeof t||"object"==typeof n){var r=s(t),a=s(n);return r!==t||a!==n?e(r,a):Object.keys(Object.assign({},t,n)).every((function(r){return e(t[r],n[r])}))}return!1};var c=n(8776);function u(e){return"/"===e.charAt(0)?e:"/"+e}function d(e){return"/"===e.charAt(0)?e.substr(1):e}function f(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function p(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function m(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function h(e,t,n,a){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),o.state=t):(void 0===(o=(0,r.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.pathname:o.pathname||(o.pathname="/"),o}function b(e,t){return e.pathname===t.pathname&&e.search===t.search&&e.hash===t.hash&&e.key===t.key&&l(e.state,t.state)}function g(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,a):n.push(a),d({action:r,location:a,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",a=h(e,t,f(),w.location);u.confirmTransitionTo(a,r,n,(function(e){e&&(w.entries[w.index]=a,d({action:r,location:a}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=w.index+e;return t>=0&&t{"use strict";var r=n(9864),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return r.isMemo(e)?i:s[e.$$typeof]||a}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var a=p(n);a&&a!==m&&e(t,a,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),h=l(n),b=0;b{"use strict";e.exports=function(e,t,n,r,a,o,i,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,a,o,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var r,a;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function a(e,t,n){return en?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var a;return(a="translate3d"===r.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,a}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=a(e,r.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(r.barSelector),u=r.speed,d=r.easing;return o.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){l(o,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var a,i=t.querySelector(r.barSelector),s=e?"-100":o(n.status||0),c=document.querySelector(r.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(a=t.querySelector(r.spinnerSelector))&&p(a),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}function a(e){return e=n(e),t[e]||(t[e]=r(e))}function o(e,t,n){t=a(t),e.style[t]=n}return function(e,t){var n,r,a=arguments;if(2==a.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&o(e,n,r);else o(e,a[1],a[2])}}();function c(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=f(e),r=n+t;c(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=f(e);c(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(a="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=a)},7418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(a){return!1}}()?Object.assign:function(e,o){for(var i,s,l=a(e),c=1;c{var r=n(5826);e.exports=p,e.exports.parse=o,e.exports.compile=function(e,t){return s(o(e,t),t)},e.exports.tokensToFunction=s,e.exports.tokensToRegExp=f;var a=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,r=[],o=0,i=0,s="",u=t&&t.delimiter||"/";null!=(n=a.exec(e));){var d=n[0],f=n[1],p=n.index;if(s+=e.slice(i,p),i=p+d.length,f)s+=f[1];else{var m=e[i],h=n[2],b=n[3],g=n[4],v=n[5],y=n[6],w=n[7];s&&(r.push(s),s="");var S=null!=h&&null!=m&&m!==h,k="+"===y||"*"===y,E="?"===y||"*"===y,x=n[2]||u,_=g||v;r.push({name:b||o++,prefix:h||"",delimiter:x,optional:E,repeat:k,partial:S,asterisk:!!w,pattern:_?c(_):w?".*":"[^"+l(x)+"]+?"})}}return i{"use strict";n.d(t,{Z:()=>o});var r=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach);E+=k.value.length,k=k.next){var x=k.value;if(t.length>e.length)return;if(!(x instanceof a)){var _,C=1;if(v){if(!(_=o(S,E,e,g))||_.index>=e.length)break;var T=_.index,A=_.index+_[0].length,P=E;for(P+=k.value.length;T>=P;)P+=(k=k.next).value.length;if(E=P-=k.value.length,k.value instanceof a)continue;for(var O=k;O!==t.tail&&(Pd.reach&&(d.reach=N);var D=k.prev;if(L&&(D=l(t,D,L),E+=L.length),c(t,D,C),k=l(t,D,new a(f,b?r.tokenize(R,b):R,y,R)),I&&l(t,k,I),C>1){var M={cause:f+","+m,reach:N};i(e,t,n,k.prev,E,M),d&&M.reach>d.reach&&(d.reach=M.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var r=t.next,a={value:n,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}function c(e,t,n){for(var r=t.next,a=0;a"+o.content+""},r}(),a=r;r.default=r,a.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},a.languages.markup.tag.inside["attr-value"].inside.entity=a.languages.markup.entity,a.languages.markup.doctype.inside["internal-subset"].inside=a.languages.markup,a.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(a.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:a.languages[t]},n.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:a.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},a.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(a.languages.markup.tag,"addAttribute",{value:function(e,t){a.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:a.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),a.languages.html=a.languages.markup,a.languages.mathml=a.languages.markup,a.languages.svg=a.languages.markup,a.languages.xml=a.languages.extend("markup",{}),a.languages.ssml=a.languages.xml,a.languages.atom=a.languages.xml,a.languages.rss=a.languages.xml,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var a=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=r.variable[1].inside,i=0;i]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},a.languages.c=a.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),a.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),a.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},a.languages.c.string],char:a.languages.c.char,comment:a.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:a.languages.c}}}}),a.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete a.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(a),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(a),function(e){var t,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var r={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},a={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:a,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:a})}(a),a.languages.javascript=a.languages.extend("clike",{"class-name":[a.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),a.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,a.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:a.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:a.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:a.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:a.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:a.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),a.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:a.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),a.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),a.languages.markup&&(a.languages.markup.tag.addInlined("script","javascript"),a.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),a.languages.js=a.languages.javascript,function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(a),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*/.source.replace(//g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\s*:\s)/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return"(?:"+a+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(o),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(a),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(//g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+o+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+o+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)|_(?:(?!_))+_)+__\b|\*\*(?:(?!\*)|\*(?:(?!\*))+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)|__(?:(?!_))+__)+_\b|\*(?:(?!\*)|\*\*(?:(?!\*))+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~))+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\]))+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n",quot:'"'},l=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(a),a.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:a.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},a.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n0)){var s=f(/^\{$/,/^\}$/);if(-1===s)continue;for(var l=n;l=0&&p(c,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],o=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function s(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function l(t,n,r){var a={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",a),a.tokens=e.tokenize(a.code,a.grammar),e.hooks.run("after-tokenize",a),a.tokens}function c(t){var n={};n["interpolation-punctuation"]=a;var o=e.tokenize(t,n);if(3===o.length){var i=[1,1];i.push.apply(i,l(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,i)}return new e.Token("interpolation",o,r.alias,t)}function u(t,n,r){var a=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),i=0,u={},d=l(a.map((function(e){if("string"==typeof e)return e;for(var n,a=e.content;-1!==t.indexOf(n=s(i++,r)););return u[n]=a,n})).join(""),n,r),f=Object.keys(u);return i=0,function e(t){for(var n=0;n=f.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=f[i],o="string"==typeof r?r:r.content,s=o.indexOf(a);if(-1!==s){++i;var l=o.substring(0,s),d=c(u[a]),p=o.substring(s+a.length),m=[];if(l&&m.push(l),m.push(d),p){var h=[p];e(h),m.push.apply(m,h)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(m)),n+=m.length-1):r.content=m}}else{var b=r.content;Array.isArray(b)?e(b):e([b])}}}(d),new e.Token(r,d,"language-"+r,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var r=0,a=n.length;r]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(a),function(e){function t(e,t){return RegExp(e.replace(//g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:(?:\s*,\s*(?:\*\s*as\s+|\{[^{}]*\}))?|\*\s*as\s+|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r*\.{3}(?:[^{}]|)*\})/.source;function o(e,t){return e=e.replace(//g,(function(){return n})).replace(//g,(function(){return r})).replace(//g,(function(){return a})),RegExp(e,t)}a=o(a).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(//.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var i=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(i).join(""):""},s=function(t){for(var n=[],r=0;r0&&n[n.length-1].tagName===i(a.content[0].content[1])&&n.pop():"/>"===a.content[a.content.length-1].content||n.push({tagName:i(a.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===a.type&&"{"===a.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===a.type&&"}"===a.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof a)&&n.length>0&&0===n[n.length-1].openedBraces){var l=i(a);r0&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(l=i(t[r-1])+l,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",l,null,l)}a.content&&"string"!=typeof a.content&&s(a.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||s(e.tokens)}))}(a),function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var r=t[n],a=[];/^\w+$/.test(n)||a.push(/\w+/.exec(n)[0]),"diff"===n&&a.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:a,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(a),a.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m},a.languages.go=a.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),a.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete a.languages.go["class-name"],function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,(function(e){if("function"==typeof o&&!o(e))return e;for(var a,s=i.length;-1!==n.code.indexOf(a=t(r,s));)++s;return i[s]=e,a})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(s){for(var l=0;l=o.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[a],d=n.tokenStack[u],f="string"==typeof c?c:c.content,p=t(r,u),m=f.indexOf(p);if(m>-1){++a;var h=f.substring(0,m),b=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),g=f.substring(m+p.length),v=[];h&&v.push.apply(v,i([h])),v.push(b),g&&v.push.apply(v,i([g])),"string"==typeof c?s.splice.apply(s,[l,1].concat(v)):c.content=v}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(a),function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:false|true)\b/,block:{pattern:/^(\s*(?:~\s*)?)[#\/]\S+?(?=\s*(?:~\s*)?$|\s)/,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&':()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")})),e.languages.hbs=e.languages.handlebars}(a),a.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},a.languages.webmanifest=a.languages.json,a.languages.less=a.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),a.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),a.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},a.languages.objectivec=a.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete a.languages.objectivec["class-name"],a.languages.objc=a.languages.objectivec,a.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/},a.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},a.languages.python["string-interpolation"].inside.interpolation.inside.rest=a.languages.python,a.languages.py=a.languages.python,a.languages.reason=a.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),a.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete a.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(a),a.languages.scss=a.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),a.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),a.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),a.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),a.languages.scss.atrule.inside.rest=a.languages.scss,function(e){var t={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},r={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:n,punctuation:/[{}()\[\];:,]/};r.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:r}},r.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:r}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:r}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:r}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:r}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:r.interpolation}},rest:r}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:r.interpolation,comment:r.comment,punctuation:/[{},]/}},func:r.func,string:r.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:r.interpolation,punctuation:/[{}()\[\];:.]/}}(a),function(e){var t=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var n=e.languages.tsx.tag;n.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}(a),a.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/};const o=a},9901:e=>{e.exports&&(e.exports={core:{meta:{path:"components/prism-core.js",option:"mandatory"},core:"Core"},themes:{meta:{path:"themes/{id}.css",link:"index.html?theme={id}",exclusive:!0},prism:{title:"Default",option:"default"},"prism-dark":"Dark","prism-funky":"Funky","prism-okaidia":{title:"Okaidia",owner:"ocodia"},"prism-twilight":{title:"Twilight",owner:"remybach"},"prism-coy":{title:"Coy",owner:"tshedor"},"prism-solarizedlight":{title:"Solarized Light",owner:"hectormatos2011 "},"prism-tomorrow":{title:"Tomorrow Night",owner:"Rosey"}},languages:{meta:{path:"components/prism-{id}",noCSS:!0,examplesPath:"examples/prism-{id}",addCheckAll:!0},markup:{title:"Markup",alias:["html","xml","svg","mathml","ssml","atom","rss"],aliasTitles:{html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",atom:"Atom",rss:"RSS"},option:"default"},css:{title:"CSS",option:"default",modify:"markup"},clike:{title:"C-like",option:"default"},javascript:{title:"JavaScript",require:"clike",modify:"markup",optional:"regex",alias:"js",option:"default"},abap:{title:"ABAP",owner:"dellagustin"},abnf:{title:"ABNF",owner:"RunDevelopment"},actionscript:{title:"ActionScript",require:"javascript",modify:"markup",owner:"Golmote"},ada:{title:"Ada",owner:"Lucretia"},agda:{title:"Agda",owner:"xy-ren"},al:{title:"AL",owner:"RunDevelopment"},antlr4:{title:"ANTLR4",alias:"g4",owner:"RunDevelopment"},apacheconf:{title:"Apache Configuration",owner:"GuiTeK"},apex:{title:"Apex",require:["clike","sql"],owner:"RunDevelopment"},apl:{title:"APL",owner:"ngn"},applescript:{title:"AppleScript",owner:"Golmote"},aql:{title:"AQL",owner:"RunDevelopment"},arduino:{title:"Arduino",require:"cpp",alias:"ino",owner:"dkern"},arff:{title:"ARFF",owner:"Golmote"},armasm:{title:"ARM Assembly",alias:"arm-asm",owner:"RunDevelopment"},arturo:{title:"Arturo",alias:"art",optional:["bash","css","javascript","markup","markdown","sql"],owner:"drkameleon"},asciidoc:{alias:"adoc",title:"AsciiDoc",owner:"Golmote"},aspnet:{title:"ASP.NET (C#)",require:["markup","csharp"],owner:"nauzilus"},asm6502:{title:"6502 Assembly",owner:"kzurawel"},asmatmel:{title:"Atmel AVR Assembly",owner:"cerkit"},autohotkey:{title:"AutoHotkey",owner:"aviaryan"},autoit:{title:"AutoIt",owner:"Golmote"},avisynth:{title:"AviSynth",alias:"avs",owner:"Zinfidel"},"avro-idl":{title:"Avro IDL",alias:"avdl",owner:"RunDevelopment"},awk:{title:"AWK",alias:"gawk",aliasTitles:{gawk:"GAWK"},owner:"RunDevelopment"},bash:{title:"Bash",alias:["sh","shell"],aliasTitles:{sh:"Shell",shell:"Shell"},owner:"zeitgeist87"},basic:{title:"BASIC",owner:"Golmote"},batch:{title:"Batch",owner:"Golmote"},bbcode:{title:"BBcode",alias:"shortcode",aliasTitles:{shortcode:"Shortcode"},owner:"RunDevelopment"},bbj:{title:"BBj",owner:"hyyan"},bicep:{title:"Bicep",owner:"johnnyreilly"},birb:{title:"Birb",require:"clike",owner:"Calamity210"},bison:{title:"Bison",require:"c",owner:"Golmote"},bnf:{title:"BNF",alias:"rbnf",aliasTitles:{rbnf:"RBNF"},owner:"RunDevelopment"},bqn:{title:"BQN",owner:"yewscion"},brainfuck:{title:"Brainfuck",owner:"Golmote"},brightscript:{title:"BrightScript",owner:"RunDevelopment"},bro:{title:"Bro",owner:"wayward710"},bsl:{title:"BSL (1C:Enterprise)",alias:"oscript",aliasTitles:{oscript:"OneScript"},owner:"Diversus23"},c:{title:"C",require:"clike",owner:"zeitgeist87"},csharp:{title:"C#",require:"clike",alias:["cs","dotnet"],owner:"mvalipour"},cpp:{title:"C++",require:"c",owner:"zeitgeist87"},cfscript:{title:"CFScript",require:"clike",alias:"cfc",owner:"mjclemente"},chaiscript:{title:"ChaiScript",require:["clike","cpp"],owner:"RunDevelopment"},cil:{title:"CIL",owner:"sbrl"},cilkc:{title:"Cilk/C",require:"c",alias:"cilk-c",owner:"OpenCilk"},cilkcpp:{title:"Cilk/C++",require:"cpp",alias:["cilk-cpp","cilk"],owner:"OpenCilk"},clojure:{title:"Clojure",owner:"troglotit"},cmake:{title:"CMake",owner:"mjrogozinski"},cobol:{title:"COBOL",owner:"RunDevelopment"},coffeescript:{title:"CoffeeScript",require:"javascript",alias:"coffee",owner:"R-osey"},concurnas:{title:"Concurnas",alias:"conc",owner:"jasontatton"},csp:{title:"Content-Security-Policy",owner:"ScottHelme"},cooklang:{title:"Cooklang",owner:"ahue"},coq:{title:"Coq",owner:"RunDevelopment"},crystal:{title:"Crystal",require:"ruby",owner:"MakeNowJust"},"css-extras":{title:"CSS Extras",require:"css",modify:"css",owner:"milesj"},csv:{title:"CSV",owner:"RunDevelopment"},cue:{title:"CUE",owner:"RunDevelopment"},cypher:{title:"Cypher",owner:"RunDevelopment"},d:{title:"D",require:"clike",owner:"Golmote"},dart:{title:"Dart",require:"clike",owner:"Golmote"},dataweave:{title:"DataWeave",owner:"machaval"},dax:{title:"DAX",owner:"peterbud"},dhall:{title:"Dhall",owner:"RunDevelopment"},diff:{title:"Diff",owner:"uranusjr"},django:{title:"Django/Jinja2",require:"markup-templating",alias:"jinja2",owner:"romanvm"},"dns-zone-file":{title:"DNS zone file",owner:"RunDevelopment",alias:"dns-zone"},docker:{title:"Docker",alias:"dockerfile",owner:"JustinBeckwith"},dot:{title:"DOT (Graphviz)",alias:"gv",optional:"markup",owner:"RunDevelopment"},ebnf:{title:"EBNF",owner:"RunDevelopment"},editorconfig:{title:"EditorConfig",owner:"osipxd"},eiffel:{title:"Eiffel",owner:"Conaclos"},ejs:{title:"EJS",require:["javascript","markup-templating"],owner:"RunDevelopment",alias:"eta",aliasTitles:{eta:"Eta"}},elixir:{title:"Elixir",owner:"Golmote"},elm:{title:"Elm",owner:"zwilias"},etlua:{title:"Embedded Lua templating",require:["lua","markup-templating"],owner:"RunDevelopment"},erb:{title:"ERB",require:["ruby","markup-templating"],owner:"Golmote"},erlang:{title:"Erlang",owner:"Golmote"},"excel-formula":{title:"Excel Formula",alias:["xlsx","xls"],owner:"RunDevelopment"},fsharp:{title:"F#",require:"clike",owner:"simonreynolds7"},factor:{title:"Factor",owner:"catb0t"},false:{title:"False",owner:"edukisto"},"firestore-security-rules":{title:"Firestore security rules",require:"clike",owner:"RunDevelopment"},flow:{title:"Flow",require:"javascript",owner:"Golmote"},fortran:{title:"Fortran",owner:"Golmote"},ftl:{title:"FreeMarker Template Language",require:"markup-templating",owner:"RunDevelopment"},gml:{title:"GameMaker Language",alias:"gamemakerlanguage",require:"clike",owner:"LiarOnce"},gap:{title:"GAP (CAS)",owner:"RunDevelopment"},gcode:{title:"G-code",owner:"RunDevelopment"},gdscript:{title:"GDScript",owner:"RunDevelopment"},gedcom:{title:"GEDCOM",owner:"Golmote"},gettext:{title:"gettext",alias:"po",owner:"RunDevelopment"},gherkin:{title:"Gherkin",owner:"hason"},git:{title:"Git",owner:"lgiraudel"},glsl:{title:"GLSL",require:"c",owner:"Golmote"},gn:{title:"GN",alias:"gni",owner:"RunDevelopment"},"linker-script":{title:"GNU Linker Script",alias:"ld",owner:"RunDevelopment"},go:{title:"Go",require:"clike",owner:"arnehormann"},"go-module":{title:"Go module",alias:"go-mod",owner:"RunDevelopment"},gradle:{title:"Gradle",require:"clike",owner:"zeabdelkhalek-badido18"},graphql:{title:"GraphQL",optional:"markdown",owner:"Golmote"},groovy:{title:"Groovy",require:"clike",owner:"robfletcher"},haml:{title:"Haml",require:"ruby",optional:["css","css-extras","coffeescript","erb","javascript","less","markdown","scss","textile"],owner:"Golmote"},handlebars:{title:"Handlebars",require:"markup-templating",alias:["hbs","mustache"],aliasTitles:{mustache:"Mustache"},owner:"Golmote"},haskell:{title:"Haskell",alias:"hs",owner:"bholst"},haxe:{title:"Haxe",require:"clike",optional:"regex",owner:"Golmote"},hcl:{title:"HCL",owner:"outsideris"},hlsl:{title:"HLSL",require:"c",owner:"RunDevelopment"},hoon:{title:"Hoon",owner:"matildepark"},http:{title:"HTTP",optional:["csp","css","hpkp","hsts","javascript","json","markup","uri"],owner:"danielgtaylor"},hpkp:{title:"HTTP Public-Key-Pins",owner:"ScottHelme"},hsts:{title:"HTTP Strict-Transport-Security",owner:"ScottHelme"},ichigojam:{title:"IchigoJam",owner:"BlueCocoa"},icon:{title:"Icon",owner:"Golmote"},"icu-message-format":{title:"ICU Message Format",owner:"RunDevelopment"},idris:{title:"Idris",alias:"idr",owner:"KeenS",require:"haskell"},ignore:{title:".ignore",owner:"osipxd",alias:["gitignore","hgignore","npmignore"],aliasTitles:{gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore"}},inform7:{title:"Inform 7",owner:"Golmote"},ini:{title:"Ini",owner:"aviaryan"},io:{title:"Io",owner:"AlesTsurko"},j:{title:"J",owner:"Golmote"},java:{title:"Java",require:"clike",owner:"sherblot"},javadoc:{title:"JavaDoc",require:["markup","java","javadoclike"],modify:"java",optional:"scala",owner:"RunDevelopment"},javadoclike:{title:"JavaDoc-like",modify:["java","javascript","php"],owner:"RunDevelopment"},javastacktrace:{title:"Java stack trace",owner:"RunDevelopment"},jexl:{title:"Jexl",owner:"czosel"},jolie:{title:"Jolie",require:"clike",owner:"thesave"},jq:{title:"JQ",owner:"RunDevelopment"},jsdoc:{title:"JSDoc",require:["javascript","javadoclike","typescript"],modify:"javascript",optional:["actionscript","coffeescript"],owner:"RunDevelopment"},"js-extras":{title:"JS Extras",require:"javascript",modify:"javascript",optional:["actionscript","coffeescript","flow","n4js","typescript"],owner:"RunDevelopment"},json:{title:"JSON",alias:"webmanifest",aliasTitles:{webmanifest:"Web App Manifest"},owner:"CupOfTea696"},json5:{title:"JSON5",require:"json",owner:"RunDevelopment"},jsonp:{title:"JSONP",require:"json",owner:"RunDevelopment"},jsstacktrace:{title:"JS stack trace",owner:"sbrl"},"js-templates":{title:"JS Templates",require:"javascript",modify:"javascript",optional:["css","css-extras","graphql","markdown","markup","sql"],owner:"RunDevelopment"},julia:{title:"Julia",owner:"cdagnino"},keepalived:{title:"Keepalived Configure",owner:"dev-itsheng"},keyman:{title:"Keyman",owner:"mcdurdin"},kotlin:{title:"Kotlin",alias:["kt","kts"],aliasTitles:{kts:"Kotlin Script"},require:"clike",owner:"Golmote"},kumir:{title:"KuMir (\u041a\u0443\u041c\u0438\u0440)",alias:"kum",owner:"edukisto"},kusto:{title:"Kusto",owner:"RunDevelopment"},latex:{title:"LaTeX",alias:["tex","context"],aliasTitles:{tex:"TeX",context:"ConTeXt"},owner:"japborst"},latte:{title:"Latte",require:["clike","markup-templating","php"],owner:"nette"},less:{title:"Less",require:"css",optional:"css-extras",owner:"Golmote"},lilypond:{title:"LilyPond",require:"scheme",alias:"ly",owner:"RunDevelopment"},liquid:{title:"Liquid",require:"markup-templating",owner:"cinhtau"},lisp:{title:"Lisp",alias:["emacs","elisp","emacs-lisp"],owner:"JuanCaicedo"},livescript:{title:"LiveScript",owner:"Golmote"},llvm:{title:"LLVM IR",owner:"porglezomp"},log:{title:"Log file",optional:"javastacktrace",owner:"RunDevelopment"},lolcode:{title:"LOLCODE",owner:"Golmote"},lua:{title:"Lua",owner:"Golmote"},magma:{title:"Magma (CAS)",owner:"RunDevelopment"},makefile:{title:"Makefile",owner:"Golmote"},markdown:{title:"Markdown",require:"markup",optional:"yaml",alias:"md",owner:"Golmote"},"markup-templating":{title:"Markup templating",require:"markup",owner:"Golmote"},mata:{title:"Mata",owner:"RunDevelopment"},matlab:{title:"MATLAB",owner:"Golmote"},maxscript:{title:"MAXScript",owner:"RunDevelopment"},mel:{title:"MEL",owner:"Golmote"},mermaid:{title:"Mermaid",owner:"RunDevelopment"},metafont:{title:"METAFONT",owner:"LaeriExNihilo"},mizar:{title:"Mizar",owner:"Golmote"},mongodb:{title:"MongoDB",owner:"airs0urce",require:"javascript"},monkey:{title:"Monkey",owner:"Golmote"},moonscript:{title:"MoonScript",alias:"moon",owner:"RunDevelopment"},n1ql:{title:"N1QL",owner:"TMWilds"},n4js:{title:"N4JS",require:"javascript",optional:"jsdoc",alias:"n4jsd",owner:"bsmith-n4"},"nand2tetris-hdl":{title:"Nand To Tetris HDL",owner:"stephanmax"},naniscript:{title:"Naninovel Script",owner:"Elringus",alias:"nani"},nasm:{title:"NASM",owner:"rbmj"},neon:{title:"NEON",owner:"nette"},nevod:{title:"Nevod",owner:"nezaboodka"},nginx:{title:"nginx",owner:"volado"},nim:{title:"Nim",owner:"Golmote"},nix:{title:"Nix",owner:"Golmote"},nsis:{title:"NSIS",owner:"idleberg"},objectivec:{title:"Objective-C",require:"c",alias:"objc",owner:"uranusjr"},ocaml:{title:"OCaml",owner:"Golmote"},odin:{title:"Odin",owner:"edukisto"},opencl:{title:"OpenCL",require:"c",modify:["c","cpp"],owner:"Milania1"},openqasm:{title:"OpenQasm",alias:"qasm",owner:"RunDevelopment"},oz:{title:"Oz",owner:"Golmote"},parigp:{title:"PARI/GP",owner:"Golmote"},parser:{title:"Parser",require:"markup",owner:"Golmote"},pascal:{title:"Pascal",alias:"objectpascal",aliasTitles:{objectpascal:"Object Pascal"},owner:"Golmote"},pascaligo:{title:"Pascaligo",owner:"DefinitelyNotAGoat"},psl:{title:"PATROL Scripting Language",owner:"bertysentry"},pcaxis:{title:"PC-Axis",alias:"px",owner:"RunDevelopment"},peoplecode:{title:"PeopleCode",alias:"pcode",owner:"RunDevelopment"},perl:{title:"Perl",owner:"Golmote"},php:{title:"PHP",require:"markup-templating",owner:"milesj"},phpdoc:{title:"PHPDoc",require:["php","javadoclike"],modify:"php",owner:"RunDevelopment"},"php-extras":{title:"PHP Extras",require:"php",modify:"php",owner:"milesj"},"plant-uml":{title:"PlantUML",alias:"plantuml",owner:"RunDevelopment"},plsql:{title:"PL/SQL",require:"sql",owner:"Golmote"},powerquery:{title:"PowerQuery",alias:["pq","mscript"],owner:"peterbud"},powershell:{title:"PowerShell",owner:"nauzilus"},processing:{title:"Processing",require:"clike",owner:"Golmote"},prolog:{title:"Prolog",owner:"Golmote"},promql:{title:"PromQL",owner:"arendjr"},properties:{title:".properties",owner:"Golmote"},protobuf:{title:"Protocol Buffers",require:"clike",owner:"just-boris"},pug:{title:"Pug",require:["markup","javascript"],optional:["coffeescript","ejs","handlebars","less","livescript","markdown","scss","stylus","twig"],owner:"Golmote"},puppet:{title:"Puppet",owner:"Golmote"},pure:{title:"Pure",optional:["c","cpp","fortran"],owner:"Golmote"},purebasic:{title:"PureBasic",require:"clike",alias:"pbfasm",owner:"HeX0R101"},purescript:{title:"PureScript",require:"haskell",alias:"purs",owner:"sriharshachilakapati"},python:{title:"Python",alias:"py",owner:"multipetros"},qsharp:{title:"Q#",require:"clike",alias:"qs",owner:"fedonman"},q:{title:"Q (kdb+ database)",owner:"Golmote"},qml:{title:"QML",require:"javascript",owner:"RunDevelopment"},qore:{title:"Qore",require:"clike",owner:"temnroegg"},r:{title:"R",owner:"Golmote"},racket:{title:"Racket",require:"scheme",alias:"rkt",owner:"RunDevelopment"},cshtml:{title:"Razor C#",alias:"razor",require:["markup","csharp"],optional:["css","css-extras","javascript","js-extras"],owner:"RunDevelopment"},jsx:{title:"React JSX",require:["markup","javascript"],optional:["jsdoc","js-extras","js-templates"],owner:"vkbansal"},tsx:{title:"React TSX",require:["jsx","typescript"]},reason:{title:"Reason",require:"clike",owner:"Golmote"},regex:{title:"Regex",owner:"RunDevelopment"},rego:{title:"Rego",owner:"JordanSh"},renpy:{title:"Ren'py",alias:"rpy",owner:"HyuchiaDiego"},rescript:{title:"ReScript",alias:"res",owner:"vmarcosp"},rest:{title:"reST (reStructuredText)",owner:"Golmote"},rip:{title:"Rip",owner:"ravinggenius"},roboconf:{title:"Roboconf",owner:"Golmote"},robotframework:{title:"Robot Framework",alias:"robot",owner:"RunDevelopment"},ruby:{title:"Ruby",require:"clike",alias:"rb",owner:"samflores"},rust:{title:"Rust",owner:"Golmote"},sas:{title:"SAS",optional:["groovy","lua","sql"],owner:"Golmote"},sass:{title:"Sass (Sass)",require:"css",optional:"css-extras",owner:"Golmote"},scss:{title:"Sass (SCSS)",require:"css",optional:"css-extras",owner:"MoOx"},scala:{title:"Scala",require:"java",owner:"jozic"},scheme:{title:"Scheme",owner:"bacchus123"},"shell-session":{title:"Shell session",require:"bash",alias:["sh-session","shellsession"],owner:"RunDevelopment"},smali:{title:"Smali",owner:"RunDevelopment"},smalltalk:{title:"Smalltalk",owner:"Golmote"},smarty:{title:"Smarty",require:"markup-templating",optional:"php",owner:"Golmote"},sml:{title:"SML",alias:"smlnj",aliasTitles:{smlnj:"SML/NJ"},owner:"RunDevelopment"},solidity:{title:"Solidity (Ethereum)",alias:"sol",require:"clike",owner:"glachaud"},"solution-file":{title:"Solution file",alias:"sln",owner:"RunDevelopment"},soy:{title:"Soy (Closure Template)",require:"markup-templating",owner:"Golmote"},sparql:{title:"SPARQL",require:"turtle",owner:"Triply-Dev",alias:"rq"},"splunk-spl":{title:"Splunk SPL",owner:"RunDevelopment"},sqf:{title:"SQF: Status Quo Function (Arma 3)",require:"clike",owner:"RunDevelopment"},sql:{title:"SQL",owner:"multipetros"},squirrel:{title:"Squirrel",require:"clike",owner:"RunDevelopment"},stan:{title:"Stan",owner:"RunDevelopment"},stata:{title:"Stata Ado",require:["mata","java","python"],owner:"RunDevelopment"},iecst:{title:"Structured Text (IEC 61131-3)",owner:"serhioromano"},stylus:{title:"Stylus",owner:"vkbansal"},supercollider:{title:"SuperCollider",alias:"sclang",owner:"RunDevelopment"},swift:{title:"Swift",owner:"chrischares"},systemd:{title:"Systemd configuration file",owner:"RunDevelopment"},"t4-templating":{title:"T4 templating",owner:"RunDevelopment"},"t4-cs":{title:"T4 Text Templates (C#)",require:["t4-templating","csharp"],alias:"t4",owner:"RunDevelopment"},"t4-vb":{title:"T4 Text Templates (VB)",require:["t4-templating","vbnet"],owner:"RunDevelopment"},tap:{title:"TAP",owner:"isaacs",require:"yaml"},tcl:{title:"Tcl",owner:"PeterChaplin"},tt2:{title:"Template Toolkit 2",require:["clike","markup-templating"],owner:"gflohr"},textile:{title:"Textile",require:"markup",optional:"css",owner:"Golmote"},toml:{title:"TOML",owner:"RunDevelopment"},tremor:{title:"Tremor",alias:["trickle","troy"],owner:"darach",aliasTitles:{trickle:"trickle",troy:"troy"}},turtle:{title:"Turtle",alias:"trig",aliasTitles:{trig:"TriG"},owner:"jakubklimek"},twig:{title:"Twig",require:"markup-templating",owner:"brandonkelly"},typescript:{title:"TypeScript",require:"javascript",optional:"js-templates",alias:"ts",owner:"vkbansal"},typoscript:{title:"TypoScript",alias:"tsconfig",aliasTitles:{tsconfig:"TSConfig"},owner:"dkern"},unrealscript:{title:"UnrealScript",alias:["uscript","uc"],owner:"RunDevelopment"},uorazor:{title:"UO Razor Script",owner:"jaseowns"},uri:{title:"URI",alias:"url",aliasTitles:{url:"URL"},owner:"RunDevelopment"},v:{title:"V",require:"clike",owner:"taggon"},vala:{title:"Vala",require:"clike",optional:"regex",owner:"TemplarVolk"},vbnet:{title:"VB.Net",require:"basic",owner:"Bigsby"},velocity:{title:"Velocity",require:"markup",owner:"Golmote"},verilog:{title:"Verilog",owner:"a-rey"},vhdl:{title:"VHDL",owner:"a-rey"},vim:{title:"vim",owner:"westonganger"},"visual-basic":{title:"Visual Basic",alias:["vb","vba"],aliasTitles:{vba:"VBA"},owner:"Golmote"},warpscript:{title:"WarpScript",owner:"RunDevelopment"},wasm:{title:"WebAssembly",owner:"Golmote"},"web-idl":{title:"Web IDL",alias:"webidl",owner:"RunDevelopment"},wgsl:{title:"WGSL",owner:"Dr4gonthree"},wiki:{title:"Wiki markup",require:"markup",owner:"Golmote"},wolfram:{title:"Wolfram language",alias:["mathematica","nb","wl"],aliasTitles:{mathematica:"Mathematica",nb:"Mathematica Notebook"},owner:"msollami"},wren:{title:"Wren",owner:"clsource"},xeora:{title:"Xeora",require:"markup",alias:"xeoracube",aliasTitles:{xeoracube:"XeoraCube"},owner:"freakmaxi"},"xml-doc":{title:"XML doc (.net)",require:"markup",modify:["csharp","fsharp","vbnet"],owner:"RunDevelopment"},xojo:{title:"Xojo (REALbasic)",owner:"Golmote"},xquery:{title:"XQuery",require:"markup",owner:"Golmote"},yaml:{title:"YAML",alias:"yml",owner:"hason"},yang:{title:"YANG",owner:"RunDevelopment"},zig:{title:"Zig",owner:"RunDevelopment"}},plugins:{meta:{path:"plugins/{id}/prism-{id}",link:"plugins/{id}/"},"line-highlight":{title:"Line Highlight",description:"Highlights specific lines and/or line ranges."},"line-numbers":{title:"Line Numbers",description:"Line number at the beginning of code lines.",owner:"kuba-kubula"},"show-invisibles":{title:"Show Invisibles",description:"Show hidden characters such as tabs and line breaks.",optional:["autolinker","data-uri-highlight"]},autolinker:{title:"Autolinker",description:"Converts URLs and emails in code to clickable links. Parses Markdown links in comments."},wpd:{title:"WebPlatform Docs",description:'Makes tokens link to WebPlatform.org documentation. The links open in a new tab.'},"custom-class":{title:"Custom Class",description:"This plugin allows you to prefix Prism's default classes (.comment can become .namespace--comment) or replace them with your defined ones (like .editor__comment). You can even add new classes.",owner:"dvkndn",noCSS:!0},"file-highlight":{title:"File Highlight",description:"Fetch external files and highlight them with Prism. Used on the Prism website itself.",noCSS:!0},"show-language":{title:"Show Language",description:"Display the highlighted language in code blocks (inline code does not show the label).",owner:"nauzilus",noCSS:!0,require:"toolbar"},"jsonp-highlight":{title:"JSONP Highlight",description:"Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).",noCSS:!0,owner:"nauzilus"},"highlight-keywords":{title:"Highlight Keywords",description:"Adds special CSS classes for each keyword for fine-grained highlighting.",owner:"vkbansal",noCSS:!0},"remove-initial-line-feed":{title:"Remove initial line feed",description:"Removes the initial line feed in code blocks.",owner:"Golmote",noCSS:!0},"inline-color":{title:"Inline color",description:"Adds a small inline preview for colors in style sheets.",require:"css-extras",owner:"RunDevelopment"},previewers:{title:"Previewers",description:"Previewers for angles, colors, gradients, easing and time.",require:"css-extras",owner:"Golmote"},autoloader:{title:"Autoloader",description:"Automatically loads the needed languages to highlight the code blocks.",owner:"Golmote",noCSS:!0},"keep-markup":{title:"Keep Markup",description:"Prevents custom markup from being dropped out during highlighting.",owner:"Golmote",optional:"normalize-whitespace",noCSS:!0},"command-line":{title:"Command Line",description:"Display a command line with a prompt and, optionally, the output/response from the commands.",owner:"chriswells0"},"unescaped-markup":{title:"Unescaped Markup",description:"Write markup without having to escape anything."},"normalize-whitespace":{title:"Normalize Whitespace",description:"Supports multiple operations to normalize whitespace in code blocks.",owner:"zeitgeist87",optional:"unescaped-markup",noCSS:!0},"data-uri-highlight":{title:"Data-URI Highlight",description:"Highlights data-URI contents.",owner:"Golmote",noCSS:!0},toolbar:{title:"Toolbar",description:"Attach a toolbar for plugins to easily register buttons on the top of a code block.",owner:"mAAdhaTTah"},"copy-to-clipboard":{title:"Copy to Clipboard Button",description:"Add a button that copies the code block to the clipboard when clicked.",owner:"mAAdhaTTah",require:"toolbar",noCSS:!0},"download-button":{title:"Download Button",description:"A button in the toolbar of a code block adding a convenient way to download a code file.",owner:"Golmote",require:"toolbar",noCSS:!0},"match-braces":{title:"Match braces",description:"Highlights matching braces.",owner:"RunDevelopment"},"diff-highlight":{title:"Diff Highlight",description:"Highlights the code inside diff blocks.",owner:"RunDevelopment",require:"diff"},"filter-highlight-all":{title:"Filter highlightAll",description:"Filters the elements the highlightAll and highlightAllUnder methods actually highlight.",owner:"RunDevelopment",noCSS:!0},treeview:{title:"Treeview",description:"A language with special styles to highlight file system tree structures.",owner:"Golmote"}}})},2885:(e,t,n)=>{const r=n(9901),a=n(9642),o=new Set;function i(e){void 0===e?e=Object.keys(r.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...o,...Object.keys(Prism.languages)];a(r,e,t).load((e=>{if(!(e in r.languages))return void(i.silent||console.warn("Language does not exist: "+e));const t="./prism-"+e;delete n.c[n(6500).resolve(t)],delete Prism.languages[e],n(6500)(t),o.add(e)}))}i.silent=!1,e.exports=i},6726:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6726},6500:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6500},9642:e=>{"use strict";var t=function(){var e=function(){};function t(e,t){Array.isArray(e)?e.forEach(t):null!=e&&t(e,0)}function n(e){for(var t={},n=0,r=e.length;n "));var s={},l=e[r];if(l){function c(t){if(!(t in e))throw new Error(r+" depends on an unknown component "+t);if(!(t in s))for(var i in a(t,o),s[t]=!0,n[t])s[i]=!0}t(l.require,c),t(l.optional,c),t(l.modify,c)}n[r]=s,o.pop()}}return function(e){var t=n[e];return t||(a(e,r),t=n[e]),t}}function a(e){for(var t in e)return!0;return!1}return function(o,i,s){var l=function(e){var t={};for(var n in e){var r=e[n];for(var a in r)if("meta"!=a){var o=r[a];t[a]="string"==typeof o?{title:o}:o}}return t}(o),c=function(e){var n;return function(r){if(r in e)return r;if(!n)for(var a in n={},e){var o=e[a];t(o&&o.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+a+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+a+" because it is a component.");n[t]=a}))}return n[r]||r}}(l);i=i.map(c),s=(s||[]).map(c);var u=n(i),d=n(s);i.forEach((function e(n){var r=l[n];t(r&&r.require,(function(t){t in d||(u[t]=!0,e(t))}))}));for(var f,p=r(l),m=u;a(m);){for(var h in f={},m){var b=l[h];t(b&&b.modify,(function(e){e in d&&(f[e]=!0)}))}for(var g in d)if(!(g in u))for(var v in p(g))if(v in u){f[g]=!0;break}for(var y in m=f)u[y]=!0}var w={getIds:function(){var e=[];return w.load((function(t){e.push(t)})),e},load:function(t,n){return function(t,n,r,a){var o=a?a.series:void 0,i=a?a.parallel:e,s={},l={};function c(e){if(e in s)return s[e];l[e]=!0;var a,u=[];for(var d in t(e))d in n&&u.push(d);if(0===u.length)a=r(e);else{var f=i(u.map((function(e){var t=c(e);return delete l[e],t})));o?a=o(f,(function(){return r(e)})):r(e)}return s[e]=a}for(var u in n)c(u);var d=[];for(var f in l)d.push(s[f]);return i(d)}(p,u,t,n)}};return w}}();e.exports=t},2703:(e,t,n)=>{"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},5697:(e,t,n)=>{e.exports=n(2703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:(e,t,n)=>{"use strict";var r=n(7294),a=n(7418),o=n(3840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n