# Hello World Smart Contract

2025-02-21: Missing steps for lock and unlock

## Requirements

* A Cup of Coffee
* The Aiken Hello World Example (You need to update the smart contract name to avoid getting the `already exists` message from Anvil API.)
  * The Smart Contract name should be in this format: `your_org/hello-world`
  * See the official documentation: [Aiken Hello World](https://aiken-lang.org/example--hello-world/basics)
* An Anvil API Key (you can use the one provided in this document to access `preprod`)
* `customer.json` with 100ADA, you can use the CLI tool to generate the wallet, then send funds from the faucet to it. ([Wallet CLI](/developer-tools/wallet-cli.md))

***

## Objectives

Interact with any Smart Contracts using Anvil API

**Objectives**

* Upload Blueprint
* Deploy Smart Contract On-Chain
* Update/Delete Blueprint
* Hello World Lock & Unlock ADA
* Get a `jsonSchema` from your blueprint to get types for the language you use.
* See below for the **code** in one file (`full.ts`)

***

## Aiken Smart Contract

<details>

<summary>Smart Contract - Update Name</summary>

**aiken.toml**

```toml
name = "your-org/your-sc-name"
version = "0.0.0"
compiler = "v1.1.10"
plutus = "v3"
license = "Apache-2.0"
description = "Aiken contracts for project 'your-org/your-sc-name'"

[repository]
user = "your-org"
project = "your-sc-name"
platform = "github"

[[dependencies]]
name = "aiken-lang/stdlib"
version = "v2.2.0"
source = "github"

[config]
```

</details>

## Helper Functions

Function to extract `validator hashes` from a `blueprint`

```typescript
function getValidators(validators: typeof blueprint.validators) {
  return [...validators.reduce((a, b) => a.set(b.hash, b) && a, new Map<string, typeof blueprint.validators[number]>()).values()];
}
```

***

## Prerequisites

You need to load your **Blueprint** like this:

```typescript
import blueprint from "./hello-world/plutus.json" with {type: "json"};
```

The **wallet used** in this guide is loaded like this:

> You also need the CSL imports and Buffer for that to work, it is only the case when you are using the wallet in the backend.

```typescript
import { Buffer } from "node:buffer";
import { FixedTransaction, PrivateKey } from "npm:@emurgo/cardano-serialization-lib-nodejs@14.1.0"; // only required due to signing in the backend.

import customer from "./customer.json" with {type: "json"}; // Optional, this guide is using this approach.
```

> You can use any wallet, like the one in your browser or with weld, but to limit the external steps and streamline the flow. This guide uses the wallet directly in the backend. You can take a look at the [signing transaction document](/guides/transaction/signing-transaction.md) to see how to use the browser wallet.

The **api key** used is this one:

```typescript
const X_API_KEY = "testnet_EyrkvCWDZqjkfLSe1pxaF0hXxUcByHEhHuXIBjt9";
```

***

## Payload

**To upload your validator on Anvil Backend**

> Benefit of doing so, will reduce the complexity and steps to interact with your smart contract. as it will be store directly in the backend. Your API Key is link with your Blueprint and will let you update and delete it if needed.

**Deploy the Smart Contract On-Chain**

```typescript
const payload = {
  changeAddress: "addr_test...",
  message: "Smart contract deployed using anvil API",
  outputs: getValidators(blueprint.validators).map(validator => ({
    address: scriptAddresses[validator.hash],
    datum: {
      type: "script",
      hash: validator.hash
    }
  }))
}
```

* `scriptAddresses`:
  * **Key** = Validator Hash
  * **Value** = Address of the Smart Contract (*Enterprise Address*)

***

## Steps

### Step 1 - Upload Blueprint

Upload your blueprint (`plutus.json`) to Anvil Backend

#### Create Blueprint

```typescript
const blueprintRegistration = await fetch("https://preprod.api.ada-anvil.app/v2/services/blueprints",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": X_API_KEY
    },
    body: JSON.stringify({
      blueprint
    })
  });

const uploadedBlueprint = await blueprintRegistration.json();
console.debug(JSON.stringify(uploadedBlueprint, null, 2))

const { scriptAddresses } = uploadedBlueprint;
```

* `scriptAddresses`: Needed for Step #2

> This API Call is an `upsert`, so if you forget the `scriptAddresses` or need to update your blueprint, you can reuse the same call.

> **Tip**: Once registered, if you need to update the name without changing the smart contract code or logic, you can safely delete the blueprint using the former name and then re-upload it.

### Step 2 - Deploy Smart Contract

> You need a valid Cardano wallet with some ADA on it (100ADA should be more than enough) [Wallet CLI](/developer-tools/wallet-cli.md)

Deploy the smart contract on-chain in order to get the reference UTXO

#### Payload to build the transaction:

```typescript
const contract = {
  changeAddress: customer.base_address_preprod,
  message: "Smart contract deployed using anvil API",
  outputs: getValidators(blueprint.validators).map(validator => ({
    address: scriptAddresses[validator.hash],
    datum: {
      type: "script",
      hash: validator.hash,
    }
  })),
};
```

#### Create the transaction

```typescript
const contractDeployed = await fetch(
  `https://preprod.api.ada-anvil.app/v2/services/transactions/build`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": X_API_KEY
    },
    body: JSON.stringify(contract),
  }
);

const contractToDeployTransaction = await contractDeployed.json();
console.log(JSON.stringify(contractToDeployTransaction));
```

#### Sign and Submit the transaction

> The signature process uses CSL for simplicity. For more information, see the [Signing a Transaction](/guides/transaction/signing-transaction.md) guide.

```typescript
// Sign the transaction using CSL.
const txToSubmitOnChain = FixedTransaction.from_bytes(
  Buffer.from(contractToDeployTransaction.complete, "hex")
);
txToSubmitOnChain.sign_and_add_vkey_signature(
  PrivateKey.from_bech32(customer.skey)
);

const urlSubmit = "https://preprod.api.ada-anvil.app/v2/services/transactions/submit";
const submitted = await fetch(urlSubmit, {
  method: "POST",
  body: JSON.stringify({
    signatures: [], // no signature required as it is part of the `txToSubmitOnChain`.
    transaction: txToSubmitOnChain.to_hex(),
  }),
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": X_API_KEY,
  },
});

const response = await submitted.json();
console.debug(response);

const { txHash } = response;
```

### Step 3 - Link Blueprint and UTXO

Update blueprint to link references to deployed validators.

```typescript
const response = await fetch(`https://preprod.api.ada-anvil.app/v2/services/blueprints`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": X_API_KEY
    },
    body: JSON.stringify({
      blueprint,
      refs: getValidators(blueprint.validators).reduce((a, b, index) => {
        a[b.hash] = { txHash, index };
        return a;
      }, {} as Record<string, { txHash: string, index: number }>),
    })
  });

const updatedBlueprint = await response.json()
console.log(updatedBlueprint);
```

### Conclusion

From here you have uploaded your blueprint and linked the reference UTXO on-chain and in Anvil Backend.

The next step is to interact with the `hello-world` Smart Contract (Lock & Unlock ADA)

***

## Full Example

<details>

<summary>full.ts</summary>

{% code overflow="wrap" %}

```typescript
import { Buffer } from "node:buffer";
import { FixedTransaction, PrivateKey } from "npm:@emurgo/cardano-serialization-lib-nodejs@14.1.0"; // only required due to signing in the backend.

import blueprint from "./plutus.json" with {type: "json"};
import customer from "./customer.json" with {type: "json"};

const X_API_KEY = "testnet_EyrkvCWDZqjkfLSe1pxaF0hXxUcByHEhHuXIBjt9";
const API_ENDPOINT = "https://preprod.api.ada-anvil.app/v2/services"

const headers = {
  "x-api-key": X_API_KEY,
  "Content-Type": "application/json",
};

function getValidators(validators: typeof blueprint.validators) {
  return [...validators.reduce((a, b) => a.set(b.hash, b) && a, new Map<string, typeof blueprint.validators[number]>()).values()];
}

const blueprintRegistration = await fetch(`${API_ENDPOINT}/blueprints`,
  {
    method: "POST",
    headers,
    body: JSON.stringify({ blueprint })
  });

const uploadedBlueprint = await blueprintRegistration.json();
console.debug("uploadedBlueprint", JSON.stringify(uploadedBlueprint, null, 2))

const { scriptAddresses } = uploadedBlueprint;

const contract = {
  changeAddress: customer.base_address_preprod,
  message: "Smart contract deployed using anvil API",
  outputs: getValidators(blueprint.validators).map(validator => ({
    address: scriptAddresses[validator.hash],
    datum: {
      type: "script",
      hash: validator.hash,
    }
  })),
};

const contractDeployed = await fetch(
  `${API_ENDPOINT}/transactions/build`,
  {
    method: "POST",
    headers,
    body: JSON.stringify(contract),
  }
);

const contractToDeployTransaction = await contractDeployed.json();
console.log("contractToDeployTransaction", JSON.stringify(contractToDeployTransaction));

// Sign the transaction using CSL.
const txToSubmitOnChain = FixedTransaction.from_bytes(
  Buffer.from(contractToDeployTransaction.complete, "hex")
);
txToSubmitOnChain.sign_and_add_vkey_signature(
  PrivateKey.from_bech32(customer.skey)
);

console.log(txToSubmitOnChain.transaction_hash().to_hex());

const urlSubmit = `${API_ENDPOINT}/transactions/submit`;
const submitted = await fetch(urlSubmit, {
  method: "POST",
  body: JSON.stringify({
    signatures: [], // no signature required as it is part of the `txToSubmitOnChain`.
    transaction: txToSubmitOnChain.to_hex(),
  }),
  headers,
});

const response = await submitted.json();
console.debug("response", response);

const { txHash } = response;

const linkBlueprintAndTxHash = await fetch(`${API_ENDPOINT}/blueprints`,
  {
    method: "POST",
    headers,
    body: JSON.stringify({
      blueprint,
      refs: getValidators(blueprint.validators).reduce((a, b, index) => {
        a[b.hash] = { txHash, index };
        return a;
      }, {} as Record<string, { txHash: string, index: number }>),
    })
  });

const updatedBlueprint = await linkBlueprintAndTxHash.json()
console.log("updatedBlueprint", updatedBlueprint);
```

{% endcode %}

</details>

***

## Usage (Hello World Lock/Unlock)

### Lock Funds

#### Payload

TODO: Explain the JSON below

```typescript
const input = {
  changeAddress: customer.base_address_preprod,
  message: "Locking my fortune using anvil API",
  outputs: [
    {
      address: await getScriptAddr(hash), // script address of the first validator
      lovelace: 2_000_000, // 1 ADA = 1_000_000 Lovelace
      datum: {
        type: "inline",
        value: {
          owner: customer.key_hash // Only the Customer will be able to unlock the funds
        },
        shape: {
          validatorHash: hash,
          purpose: "spend"
        }
      }
    }
  ],
};
```

### Unlock Funds

#### Payload

TODO: Explain the JSON below

```typescript
const input = {
  changeAddress: customer.base_address_preprod,
  message: "Unlock my fortune using anvil API",
  scriptInteractions: [
    {
      hash,
      purpose: "spend",
      // This Output ref and index is the UTXO locked at the previous step.
      outputRef: {
        txHash: "7ac8f6922d51ffe2980e73c57c985b3906795440b5a565cc8806899dc88b110e", // ACTION: Replace with your txHash
        index: 0, // ACTION: Replace with you index
      },
      redeemer: { // Aka. Smart contract Parameters
        type: "json",
        value: {
          msg: Buffer.from("Bonjour Monde!!", "utf8").toString("hex") // ACTION: Replace with your String
        }
      }
    }
  ],
  requiredSigners: [customer.key_hash], // Aka. extra_signatories
};
```

### Full Example - Lock Fund

<details>

<summary>lock.ts</summary>

{% code overflow="wrap" %}

```typescript
import { Buffer } from "node:buffer";
import {
  FixedTransaction,
  PrivateKey
} from "npm:@emurgo/cardano-serialization-lib-nodejs@14.1.0";

import blueprint from "./hello-world/plutus.json" with {type: "json"}; // NOTE: You only need the hash.
import customer from "./customer.json" with {type: "json"};

const X_API_KEY = "testnet_EyrkvCWDZqjkfLSe1pxaF0hXxUcByHEhHuXIBjt9";

// Save the hash in your database or backend.
// You are gonna need this hash everytime you need to interact with the smart contract.
// In this example we are loading it from the blueprint, but you do not need the blueprint.
const hash = blueprint.validators[0].hash;

async function getScriptAddr(hash: string): Promise<string> {
  const response = await fetch(`https://preprod.api.ada-anvil.app/v2/services/validators/${hash}/address`, {
    method: "GET",
    headers: {
      "x-api-key": X_API_KEY
    },
  });

  const scriptAddress = await response.json();
  console.debug("scriptAddress", scriptAddress)
  return scriptAddress.hex as string;
}

// Send 2 ADA to the Smart Contract (Lock ADA)
const input = {
  changeAddress: customer.base_address_preprod,
  message: "Locking my fortune using anvil API",
  outputs: [
    {
      address: await getScriptAddr(hash), // script address of the first validator
      lovelace: 2_000_000, // 1 ADA = 1_000_000 Lovelace
      datum: {
        type: "inline",
        value: {
          owner: customer.key_hash // Only the Customer will be able to unlock the funds
        },
        shape: {
          validatorHash: hash,
          purpose: "spend"
        }
      }
    }
  ],
};

const response = await fetch(
  `https://preprod.api.ada-anvil.app/v2/services/transactions/build`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": X_API_KEY
    },
    body: JSON.stringify(input),
  }
);

const result = await response.json()
console.log("result", result);
const txToSign = result.complete;

// Sign transaction directly in the backend
const txToSubmitOnChain = FixedTransaction.from_bytes(
  Buffer.from(txToSign, "hex")
);
// This sign the tx and add vkeys to the txToSubmitOnChain, so in submit we don't need to provide signatures
txToSubmitOnChain.sign_and_add_vkey_signature(
  PrivateKey.from_bech32(customer.skey)
);


const urlSubmit = "https://preprod.api.ada-anvil.app/v2/services/transactions/submit";
const submitted = await fetch(urlSubmit, {
  method: "POST",
  body: JSON.stringify({
    signatures: [],
    transaction: txToSubmitOnChain.to_hex(),
  }),
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": X_API_KEY,
  },
});

const submittedResponse = await submitted.json();
console.debug("submittedResponse", submittedResponse);
```

{% endcode %}

</details>

### Full Example - Unlock Fund

<details>

<summary>unlock.ts</summary>

{% code overflow="wrap" %}

```typescript
import { Buffer } from "node:buffer";
import { FixedTransaction, PrivateKey } from "npm:@emurgo/cardano-serialization-lib-nodejs@14.1.0"; // update utilities doc.

import blueprint from "./hello-world/plutus.json" with {type: "json"}; // NOTE: You only need the hash.
import customer from "./customer.json" with {type: "json"};

const X_API_KEY = "testnet_EyrkvCWDZqjkfLSe1pxaF0hXxUcByHEhHuXIBjt9";

// Save the hash in your database or backend.
// You are gonna need this hash everytime you need to interact with the smart contract.
// In this example we are loading it from the blueprint, but you do not need the blueprint.
const hash = blueprint.validators[0].hash;

const input = {
  changeAddress: customer.base_address_preprod,
  message: "Unlock my fortune using anvil API",
  scriptInteractions: [
    {
      hash,
      purpose: "spend",
      // This Output ref and index is the UTXO locked at the previous step.
      outputRef: {
        txHash: "7ac8f6922d51ffe2980e73c57c985b3906795440b5a565cc8806899dc88b110e", // ACTION: Replace with your txHash
        index: 0, // ACTION: Replace with you index
      },
      redeemer: { // Aka. Smart contract Parameters
        type: "json",
        value: {
          msg: Buffer.from("Bonjour Monde!!", "utf8").toString("hex") // ACTION: Replace with your String
        }
      }
    }
  ],
  requiredSigners: [customer.key_hash], // Aka. extra_signatories
};

const response = await fetch(
  `https://preprod.api.ada-anvil.app/v2/services/transactions/build`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": X_API_KEY
    },
    body: JSON.stringify(input),
  }
);


const result = await response.json()
console.log("result", result);
const txToSign = result.complete;

// Sign transaction directly in the backend
const txToSubmitOnChain = FixedTransaction.from_bytes(
  Buffer.from(txToSign, "hex")
);
// This sign the tx and add vkeys to the txToSubmitOnChain, so in submit we don't need to provide signautres
txToSubmitOnChain.sign_and_add_vkey_signature(
  PrivateKey.from_bech32(customer.skey)
);

const urlSubmit = "https://preprod.api.ada-anvil.app/v2/services/transactions/submit";
const submitted = await fetch(urlSubmit, {
  method: "POST",
  body: JSON.stringify({
    signatures: [], // no signature required as it is part of the `txToSubmitOnChain`.
    transaction: txToSubmitOnChain.to_hex(),
  }),
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": X_API_KEY,
  },
})

const submittedResponse = await submitted.json();
console.debug("submittedResponse", submittedResponse);

```

{% endcode %}

</details>

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.ada-anvil.io/guides/smart-contract/hello-world-smart-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
