-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
245 additions
and
212 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# Marketplace Example | ||
|
||
The following code shows what the off-chain code looks like for basic NFT marketplace that uses the `Hollow` SDK. | ||
|
||
The idea is simple: the marketplace address can lock NFT and release them only if the correct price for the NFT is paid. To accomplish that, our off-chain component is going to do the following: | ||
|
||
- for each time our marketplace address receives an UTxO representing an buyable asset, we store a reference in database table. | ||
- for each time our marketplace address releases an UTxO representing a buyable asset, we remove it from our database table. | ||
- if someone wants to query the list available assets, we lookup available items in the db and provide them as a json values. | ||
- if someone want to buy one of the available assets, we create a partial transaction and return it for the user to balance & sign. | ||
|
||
Here's the code: | ||
|
||
::warning:: this is WIP, specific function names and structures will most likely suffer some changes. The essence of the framework and the semantic meaning of the artifacts will remain. | ||
|
||
```rust | ||
const MARKETPLACE: &str = "addr1xxx"; | ||
|
||
#[derive(Datum)] | ||
struct AssetDatum { | ||
price: PlutusInt, | ||
} | ||
|
||
#[chain_event] | ||
#[match_inbound_utxo(to_address=MARKETPLACE)] | ||
fn on_new_asset(utxo: UTxO) -> Result<()> { | ||
let db = use_extension::<Database>(); | ||
|
||
let datum = utxo.datum_as::<AssetDatum>(); | ||
|
||
if datum.is_none() { | ||
bail!("unexpected utxo"); | ||
} | ||
|
||
for asset in utxo.assets() { | ||
db.execute( | ||
"INSERT INTO (policy, asset, price) VALUES ({}, {}, {})", | ||
asset.policy_id, | ||
asset.asset_name, | ||
datum.price, | ||
); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
#[chain_event] | ||
#[match_outbound_utxo(from_address=MARKETPLACE)] | ||
fn on_asset_sold(utxo: UTxO) -> Result<()> { | ||
let db = use_extension::<Database>(); | ||
|
||
for asset in utxo.assets() { | ||
db.execute( | ||
"DELETE FROM assets WHERE policy={} and asset={}", | ||
asset.policy_id, | ||
asset.asset_name, | ||
); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
#[extrinsic_event] | ||
#[match_http_route(path = "/assets", method = "GET")] | ||
fn query_assets() -> Result<JsonValue> { | ||
let db = use_extension::<Database>(); | ||
|
||
let assets = db.query_all("SELECT * from assets;").to_json(); | ||
|
||
Ok(assets) | ||
} | ||
|
||
#[derive(Serialize, Deserialize)] | ||
struct Order { | ||
policy_id: String, | ||
asset_name: String, | ||
buyer: Address, | ||
} | ||
|
||
#[extrinsic_event] | ||
#[match_http_route(path = "/orders", method = "POST")] | ||
fn create_order(params: Order) -> Result<PartialTx> { | ||
let db = use_extension::<Database>(); | ||
|
||
let asset = db.query_first( | ||
"SELECT * from assets WHERE policy={}, name={};", | ||
params.policy_id, | ||
params.asset_name, | ||
); | ||
|
||
if asset.is_none() { | ||
bail!("we don't have that asset"); | ||
} | ||
|
||
let market = party_from_address(MARKETPLACE); | ||
let buyer = party_from_address(params.buyer); | ||
|
||
let tx = TxBuilder::new() | ||
.transfer_asset( | ||
market, // from party | ||
buyer, // to party | ||
params.policy_id, | ||
params.asset_name, | ||
TransferQuantity::All, | ||
) | ||
.output_ada( | ||
market, // to party | ||
asset.price, // lovelace amount | ||
) | ||
.build(); | ||
|
||
Ok(tx) | ||
} | ||
``` | ||
|
||
|
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.