Skip to content

Commit

Permalink
Merge branch 'nft-fest'
Browse files Browse the repository at this point in the history
  • Loading branch information
ilbertt committed Sep 13, 2024
2 parents d5ded76 + 5beea56 commit 28bafa5
Show file tree
Hide file tree
Showing 17 changed files with 195 additions and 104 deletions.
12 changes: 12 additions & 0 deletions available-prizes.did
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(
vec {
record { variant { icp = 10_000_000 : nat }; opt (10 : nat8) };
record { variant { icp = 10_000_000 : nat }; opt (10 : nat8) };
record { variant { ckBtc = 1_500 : nat }; opt (10 : nat8) };
record { variant { ckBtc = 1_500 : nat }; opt (10 : nat8) };
record { variant { merch = "Pen" }; opt (18 : nat8) };
record { variant { merch = "Pen" }; opt (16 : nat8) };
record { variant { merch = "Pen" }; opt (16 : nat8) };
record { variant { special = "jackpot" }; opt (10 : nat8) };
},
)
8 changes: 8 additions & 0 deletions current-admins.did
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(
vec {
principal "e3b3e-2qnk3-4g7uc-376eu-n3gim-gux6z-nshf6-xmrfg-yqihp-zeyol-bae";
principal "3zdpk-xwqme-jvghw-4zm7x-kfacg-mbkfd-7gpy7-q3m57-xkzba-z3p7u-bae";
principal "tk7wl-3gkcq-4swix-bsajd-o4tfd-acxlk-22npa-6dc77-f2f23-iacqw-jae";
principal "bcuet-2cf2x-ye6r4-2jipj-euxif-eduqz-nfpid-cy2ej-3t6zq-kivmc-tqe";
},
)
14 changes: 6 additions & 8 deletions deps/candid/rdmx6-jaaaa-aaaaa-aaadq-cai.did
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,9 @@ type InternetIdentityStats = record {
};
archive_info: ArchiveInfo;
canister_creation_cycles_cost: nat64;
max_num_latest_delegation_origins: nat64;
latest_delegation_origins: vec FrontendHostname
// Map from event aggregation to a sorted list of top 100 sub-keys to their weights.
// Example: {"prepare_delegation_count 24h ic0.app": [{"https://dapp.com", 100}, {"https://dapp2.com", 50}]}
event_aggregations: vec record {text; vec record {text; nat64}};
};

// Configuration parameters related to the archive.
Expand Down Expand Up @@ -227,9 +228,6 @@ type InternetIdentityInit = record {
canister_creation_cycles_cost : opt nat64;
// Rate limit for the `register` call.
register_rate_limit : opt RateLimitConfig;
// Maximum number of latest delegation origins to track.
// Default: 1000
max_num_latest_delegation_origins : opt nat64;
// Maximum number of inflight captchas.
// Default: 500
max_inflight_captchas: opt nat64;
Expand Down Expand Up @@ -538,9 +536,9 @@ service : (opt InternetIdentityInit) -> {
http_request_update: (request: HttpRequest) -> (HttpResponse);

deploy_archive: (wasm: blob) -> (DeployArchiveResult);
/// Returns a batch of entries _sorted by sequence number_ to be archived.
/// This is an update call because the archive information _must_ be certified.
/// Only callable by this IIs archive canister.
// Returns a batch of entries _sorted by sequence number_ to be archived.
// This is an update call because the archive information _must_ be certified.
// Only callable by this IIs archive canister.
fetch_entries: () -> (vec BufferedArchiveEntry);
acknowledge_entries: (sequence_number: nat64) -> ();

Expand Down
4 changes: 2 additions & 2 deletions deps/pulled.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"canisters": {
"rdmx6-jaaaa-aaaaa-aaadq-cai": {
"name": "internet-identity",
"wasm_hash": "764cff569a98a3c4d54cba6750fda63f554fc53e7d42a6365d9bdec3280d63c3",
"wasm_hash_download": "764cff569a98a3c4d54cba6750fda63f554fc53e7d42a6365d9bdec3280d63c3",
"wasm_hash": "e039c7ab988593b23fa7113fa23cd29e959805e3d49a82fadaf408e528bfc6e2",
"wasm_hash_download": "e039c7ab988593b23fa7113fa23cd29e959805e3d49a82fadaf408e528bfc6e2",
"init_guide": "Use '(null)' for sensible defaults. See the candid interface for more details.",
"init_arg": null,
"candid_args": "(opt InternetIdentityInit)",
Expand Down
3 changes: 0 additions & 3 deletions dfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
"type": "motoko"
},
"fortune-wheel-booth-frontend": {
"dependencies": [
"fortune-wheel-booth-backend"
],
"source": [
"src/fortune-wheel-booth-frontend/dist"
],
Expand Down
14 changes: 7 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions scripts/download-idl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

download_candid() {
local canister_name="$1"

# Check if dfx.json exists
if [ ! -f "dfx.json" ]; then
echo "Error: dfx.json not found"
return 1
fi

# Extract the URL and the name using jq
local url=$(jq -r ".canisters.\"$canister_name\".candid" dfx.json)
local name=$(jq -r ".canisters.\"$canister_name\".remote.id.ic" dfx.json)

# Check if the URL and name are not null
if [ "$url" == "null" ] || [ "$name" == "null" ]; then
echo "Error: Unable to extract URL or name from dfx.json for canister $canister_name"
return 1
fi

# Download the file from the URL
local output_file=".dfx/ic/canisters/idl/$name.did"
curl -o "$output_file" "$url"

# Check if the download was successful
if [ $? -ne 0 ]; then
echo "Error: Failed to download $url"
return 1
fi

echo "Downloaded $url to $output_file"
return 0
}

mkdir -p .dfx/ic/canisters/idl
# Call the function with the arguments arg1, arg2, and arg3
for arg in "icp_ledger" "ckbtc_ledger" "cketh_ledger" "ckusdc_ledger"; do
download_candid "$arg"
done
109 changes: 74 additions & 35 deletions src/fortune-wheel-booth-backend/main.mo
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import Order "mo:base/Order";
import Buffer "mo:base/Buffer";
import TrieSet "mo:base/TrieSet";
import Fuzz "mo:fuzz";
import Debug "mo:base/Debug";

import IcpLedger "canister:icp_ledger";
import ckBtcLedger "canister:ckbtc_ledger";
import ckEthLedger "canister:cketh_ledger";
import ckUsdcLedger "canister:ckusdc_ledger";

shared ({ caller = initialController }) actor class Main() {
shared ({ caller = initialController }) actor class Main() = self {
type Prize = {
#icp : Nat;
#ckBtc : Nat;
Expand All @@ -33,35 +34,44 @@ shared ({ caller = initialController }) actor class Main() {
transactionBlockIndex : ?Nat;
};

// ICP and ckBTC have 8 decimals: 100_000_000
let ICP_TX_AMOUNT_LIMIT = 20_000_000;
let CKBTC_TX_AMOUNT_LIMIT = 2_000;
// ckETH has 18 decimals: 1_000_000_000_000_000_000
let CKETH_TX_AMOUNT_LIMIT = 1_000_000_000_000_000;
// ckUSDC has 6 decimals: 1_000_000
let CKUSDC_TX_AMOUNT_LIMIT = 1_500_000;

// exchange rates from Coinbase @ 2024-07-24 21:00 CEST
let icp_amount = 11_800_000; // 0.118 ICP ~ $1
let ckbtc_amount = 1_720; // 0.0000172 ckBTC ~ $1
let cketh_amount = 424_000_000_000_000; // 0.000424 ckETH ~ $1
let ckusdc_amount = 1_000_000; // 1 ckUSDC ~ $1

/// The ?Nat8 is the quantity available for that prize. `null` means unlimited.
///
/// The prizes with a maximum quantity are removed when they reach 0.
private stable var prizesEntries : [(Prize, ?Nat8)] = [
// -- tokens --
// ICP and ckBTC have 8 decimals: 100_000_000
(#icp(8_200_000), ?10), // 0.082 ICP ~ $1
(#ckBtc(1_500), ?10), // 0.000015 ckBTC ~ $1
// ckETH has 18 decimals: 1_000_000_000_000_000_000
(#ckEth(260_000_000_000_000), ?10), // 0.00026 ckETH ~ $1
// ckUSDC has 6 decimals: 1_000_000
(#ckUsdc(1_000_000), ?10), // 1 ckUSDC ~ $1
(#icp(icp_amount), null),
(#ckBtc(ckbtc_amount), null),
(#ckEth(cketh_amount), null),
(#ckEth(cketh_amount), null),
(#ckUsdc(ckusdc_amount), null),
// -- merch --
// increase the probability of getting the merch prize by repeating it
(#merch("Tshirt"), ?12),
(#merch("Tshirt"), ?12),
(#merch("Tshirt"), ?12),
(#merch("Pen"), ?18),
(#merch("Pen"), ?18),
(#merch("tShirt"), ?20),
(#merch("pen"), null),
// -- special --
(#special("jackpot"), ?20),
(#noPrize, null), // unlimited
(#special("jackpot"), ?5),
];
var prizes : Buffer.Buffer<(Prize, ?Nat8)> = Buffer.fromArray(prizesEntries);

private stable var adminPrincipals = TrieSet.fromArray<Principal>([initialController], Principal.hash, Principal.equal);

private stable var extractedPrincipalsEntries : [(Principal, Extraction)] = [];
private let extractedPrincipals = TrieMap.fromEntries<Principal, Extraction>(extractedPrincipalsEntries.vals(), Principal.equal, Principal.hash);
var extracting = false;

// persist non-stable structures: https://internetcomputer.org/docs/current/motoko/main/canister-maintenance/upgrades#preupgrade-and-postupgrade-system-methods
system func preupgrade() {
Expand Down Expand Up @@ -107,6 +117,10 @@ shared ({ caller = initialController }) actor class Main() {
};

public shared ({ caller }) func extract(receiver : Principal) : async Extraction {
if (extracting) {
throw Error.reject("Extraction already in progress");
};

if (not isAdmin(caller)) {
throw Error.reject("Only admins can extract");
};
Expand All @@ -123,20 +137,37 @@ shared ({ caller = initialController }) actor class Main() {
throw Error.reject("Already extracted for this principal");
};

extracting := true;

let prize = await getRandomPrize();

let transactionBlockIndex = switch (prize) {
case (#icp(amount)) {
?(await transferIcp(receiver, amount));
?(await transferIcp(receiver, amount, true));
};
case (#ckBtc(amount)) {
?(await transferCkBtc(receiver, amount));
?(await transferCkBtc(receiver, amount, true));
};
case (#ckEth(amount)) {
?(await transferCkEth(receiver, amount));
?(await transferCkEth(receiver, amount, true));
};
case (#ckUsdc(amount)) {
?(await transferCkUsdc(receiver, amount));
?(await transferCkUsdc(receiver, amount, true));
};
case (#special("jackpot")) {
let icp_transfer = transferIcp(receiver, icp_amount, true);
let ckbtc_transfer = transferCkBtc(receiver, ckbtc_amount, true);
let cketh_transfer = transferCkEth(receiver, cketh_amount, true);
let ckusdc_transfer = transferCkUsdc(receiver, ckusdc_amount, true);
let icp_idx = await icp_transfer;
Debug.print("Jackpot: ICP block index: " # debug_show (icp_idx));
let ckbtc_idx = await ckbtc_transfer;
Debug.print("Jackpot: ckBTC block index: " # debug_show (ckbtc_idx));
let cketh_idx = await cketh_transfer;
Debug.print("Jackpot: ckETH block index: " # debug_show (cketh_idx));
let ckusdc_idx = await ckusdc_transfer;
Debug.print("Jackpot: ckUSDC block index: " # debug_show (ckusdc_idx));
null;
};
case (_) { null };
};
Expand All @@ -149,6 +180,8 @@ shared ({ caller = initialController }) actor class Main() {

extractedPrincipals.put(receiver, extraction);

extracting := false;

extraction;
};

Expand Down Expand Up @@ -179,9 +212,9 @@ shared ({ caller = initialController }) actor class Main() {
};
};

private func transferIcp(receiver : Principal, amount : Nat) : async Nat {
if (amount > 100_000_000) {
throw Error.reject("ICP amount must be less than 100_000_000");
private func transferIcp(receiver : Principal, amount : Nat, safe : Bool) : async Nat {
if (safe and amount > ICP_TX_AMOUNT_LIMIT) {
throw Error.reject("ICP amount must be less than" # debug_show (ICP_TX_AMOUNT_LIMIT));
};

let transferRes = await IcpLedger.icrc1_transfer({
Expand All @@ -203,9 +236,9 @@ shared ({ caller = initialController }) actor class Main() {
};
};

private func transferCkBtc(receiver : Principal, amount : Nat) : async Nat {
if (amount > 50_000) {
throw Error.reject("ckBTC amount must be less than 50_000");
private func transferCkBtc(receiver : Principal, amount : Nat, safe : Bool) : async Nat {
if (safe and amount > CKBTC_TX_AMOUNT_LIMIT) {
throw Error.reject("ckBTC amount must be less than" # debug_show (CKBTC_TX_AMOUNT_LIMIT));
};

let transferRes = await ckBtcLedger.icrc1_transfer({
Expand All @@ -227,9 +260,9 @@ shared ({ caller = initialController }) actor class Main() {
};
};

private func transferCkEth(receiver : Principal, amount : Nat) : async Nat {
if (amount > 10_000_000_000_000_000) {
throw Error.reject("ckETH amount must be less than 10_000_000_000_000_000");
private func transferCkEth(receiver : Principal, amount : Nat, safe : Bool) : async Nat {
if (safe and amount > CKETH_TX_AMOUNT_LIMIT) {
throw Error.reject("ckETH amount must be less than" # debug_show (CKETH_TX_AMOUNT_LIMIT));
};

let transferRes = await ckEthLedger.icrc1_transfer({
Expand All @@ -251,9 +284,9 @@ shared ({ caller = initialController }) actor class Main() {
};
};

private func transferCkUsdc(receiver : Principal, amount : Nat) : async Nat {
if (amount > 1_100_000) {
throw Error.reject("ckBTC amount must be less than 1_100_000");
private func transferCkUsdc(receiver : Principal, amount : Nat, safe : Bool) : async Nat {
if (safe and amount > CKUSDC_TX_AMOUNT_LIMIT) {
throw Error.reject("ckBTC amount must be less than " # debug_show (CKUSDC_TX_AMOUNT_LIMIT));
};

let transferRes = await ckUsdcLedger.icrc1_transfer({
Expand Down Expand Up @@ -309,6 +342,12 @@ shared ({ caller = initialController }) actor class Main() {
Iter.toArray(extractedPrincipals.entries());
};

public func clearExtractions() {
for (key in extractedPrincipals.keys()) {
extractedPrincipals.delete(key);
};
};

type ManualSendTokens = {
#icp : Nat;
#ckBtc : Nat;
Expand Down Expand Up @@ -336,16 +375,16 @@ shared ({ caller = initialController }) actor class Main() {

switch (tokens) {
case (#icp(amount)) {
await transferIcp(receiver, amount);
await transferIcp(receiver, amount, false);
};
case (#ckBtc(amount)) {
await transferCkBtc(receiver, amount);
await transferCkBtc(receiver, amount, false);
};
case (#ckEth(amount)) {
await transferCkEth(receiver, amount);
await transferCkEth(receiver, amount, false);
};
case (#ckUsdc(amount)) {
await transferCkUsdc(receiver, amount);
await transferCkUsdc(receiver, amount, false);
};
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ function FortuneWheelPage() {

const onStopSpinning = useCallback(() => {
setShowModalPrize(true);
setMustSpin(false);

setTimeout(() => {
setShowModalPrize(false);
setMustSpin(false);
setPrizeNumber(-1);
}, PRIZE_MODAL_DURATION_MILLIS);
}, []);
Expand Down
2 changes: 1 addition & 1 deletion src/fortune-wheel-booth-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@tsparticles/slim": "^3.4.0",
"@yudiel/react-qr-scanner": "2.0.0-beta.3",
"react": "^18.2.0",
"react-custom-roulette": "^1.4.1",
"react-custom-roulette": "^1.3.2",
"react-dom": "^18.2.0"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit 28bafa5

Please sign in to comment.