From f0e7fbd6a6db6bb60f4b6a065952fc518b566251 Mon Sep 17 00:00:00 2001 From: Saeed Dadkhah Date: Fri, 21 Jun 2024 17:41:03 +0330 Subject: [PATCH] Remove RPS and leaderboard from the core. They're moved to a separate repo --- apps/rock-paper-scissors/Cargo.toml | 17 - apps/rock-paper-scissors/build.sh | 18 - apps/rock-paper-scissors/src/choice.rs | 44 -- apps/rock-paper-scissors/src/commit.rs | 35 -- apps/rock-paper-scissors/src/errors.rs | 30 -- apps/rock-paper-scissors/src/key.rs | 82 ---- apps/rock-paper-scissors/src/lib.rs | 217 ---------- apps/rock-paper-scissors/src/player_idx.rs | 30 -- apps/rock-paper-scissors/src/repr.rs | 152 ------- contracts/leaderboard/Cargo.toml | 20 - contracts/leaderboard/build.sh | 17 - .../leaderboard/relayer/mock-ws-server.js | 41 -- contracts/leaderboard/relayer/package.json | 13 - contracts/leaderboard/relayer/relayer.js | 149 ------- contracts/leaderboard/relayer/ws.js | 50 --- contracts/leaderboard/relayer/yarn.lock | 379 ------------------ contracts/leaderboard/src/lib.rs | 85 ---- contracts/leaderboard/tests/sandbox.rs | 66 --- 18 files changed, 1445 deletions(-) delete mode 100644 apps/rock-paper-scissors/Cargo.toml delete mode 100755 apps/rock-paper-scissors/build.sh delete mode 100644 apps/rock-paper-scissors/src/choice.rs delete mode 100644 apps/rock-paper-scissors/src/commit.rs delete mode 100644 apps/rock-paper-scissors/src/errors.rs delete mode 100644 apps/rock-paper-scissors/src/key.rs delete mode 100644 apps/rock-paper-scissors/src/lib.rs delete mode 100644 apps/rock-paper-scissors/src/player_idx.rs delete mode 100644 apps/rock-paper-scissors/src/repr.rs delete mode 100644 contracts/leaderboard/Cargo.toml delete mode 100755 contracts/leaderboard/build.sh delete mode 100644 contracts/leaderboard/relayer/mock-ws-server.js delete mode 100644 contracts/leaderboard/relayer/package.json delete mode 100644 contracts/leaderboard/relayer/relayer.js delete mode 100644 contracts/leaderboard/relayer/ws.js delete mode 100644 contracts/leaderboard/relayer/yarn.lock delete mode 100644 contracts/leaderboard/src/lib.rs delete mode 100644 contracts/leaderboard/tests/sandbox.rs diff --git a/apps/rock-paper-scissors/Cargo.toml b/apps/rock-paper-scissors/Cargo.toml deleted file mode 100644 index 5f650be68..000000000 --- a/apps/rock-paper-scissors/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "rock-paper-scissors" -version = "0.1.0" -authors.workspace = true -edition.workspace = true -repository.workspace = true -license.workspace = true - -[lib] -crate-type = ["cdylib"] - -[dependencies] -bs58.workspace = true -calimero-sdk = { path = "../../crates/sdk" } -ed25519-dalek = { workspace = true, features = ["rand_core"] } -rand_chacha.workspace = true -sha3.workspace = true diff --git a/apps/rock-paper-scissors/build.sh b/apps/rock-paper-scissors/build.sh deleted file mode 100755 index cdf7c2b96..000000000 --- a/apps/rock-paper-scissors/build.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -set -e - -cd "$(dirname $0)" - -TARGET="${CARGO_TARGET_DIR:-../../target}" - -rustup target add wasm32-unknown-unknown - -cargo build --target wasm32-unknown-unknown --profile app-release - -mkdir -p res - -cp $TARGET/wasm32-unknown-unknown/app-release/rock_paper_scissors.wasm ./res/ - -if command -v wasm-opt > /dev/null; then - wasm-opt -Oz ./res/rock_paper_scissors.wasm -o ./res/rock_paper_scissors.wasm -fi diff --git a/apps/rock-paper-scissors/src/choice.rs b/apps/rock-paper-scissors/src/choice.rs deleted file mode 100644 index 653c1e607..000000000 --- a/apps/rock-paper-scissors/src/choice.rs +++ /dev/null @@ -1,44 +0,0 @@ -use std::cmp::Ordering; - -use calimero_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use calimero_sdk::serde::{Deserialize, Serialize}; - -use crate::commit::{Commitment, Nonce}; - -#[derive( - Eq, Copy, Clone, Debug, PartialEq, Serialize, Deserialize, BorshSerialize, BorshDeserialize, -)] -#[borsh(crate = "calimero_sdk::borsh")] -#[serde(crate = "calimero_sdk::serde")] -#[repr(u8)] -pub enum Choice { - Rock, - Paper, - Scissors, -} - -use Choice::*; - -impl Choice { - pub fn determine(commitment: &Commitment, nonce: &Nonce) -> Option { - let choices = [Rock, Paper, Scissors]; - - for choice in choices { - if *commitment == Commitment::of(choice, nonce) { - return Some(choice); - } - } - - None - } -} - -impl PartialOrd for Choice { - fn partial_cmp(&self, other: &Self) -> Option { - match (self, other) { - (Rock, Scissors) | (Scissors, Paper) | (Paper, Rock) => Some(Ordering::Greater), - (Scissors, Rock) | (Paper, Scissors) | (Rock, Paper) => Some(Ordering::Less), - _ => Some(Ordering::Equal), - } - } -} diff --git a/apps/rock-paper-scissors/src/commit.rs b/apps/rock-paper-scissors/src/commit.rs deleted file mode 100644 index 06f2c4277..000000000 --- a/apps/rock-paper-scissors/src/commit.rs +++ /dev/null @@ -1,35 +0,0 @@ -use calimero_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use sha3::{Digest, Sha3_256}; - -use crate::Choice; - -#[derive(Eq, Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize)] -#[borsh(crate = "calimero_sdk::borsh")] -pub struct Commitment([u8; 32]); - -pub type Nonce = [u8; 32]; - -impl Commitment { - pub fn of(choice: Choice, nonce: &Nonce) -> Self { - let mut hasher = Sha3_256::new(); - - hasher.update(&[choice as u8]); - hasher.update(nonce); - - Commitment(hasher.finalize().into()) - } - - pub const fn from_bytes(bytes: &[u8; 32]) -> Self { - Commitment(*bytes) - } - - pub const fn to_bytes(&self) -> [u8; 32] { - self.0 - } -} - -impl AsRef<[u8]> for Commitment { - fn as_ref(&self) -> &[u8] { - &self.0 - } -} diff --git a/apps/rock-paper-scissors/src/errors.rs b/apps/rock-paper-scissors/src/errors.rs deleted file mode 100644 index 2d53551bc..000000000 --- a/apps/rock-paper-scissors/src/errors.rs +++ /dev/null @@ -1,30 +0,0 @@ -use calimero_sdk::serde::Serialize; - -#[derive(Debug, Serialize)] -#[serde(crate = "calimero_sdk::serde")] -pub enum JoinError { - GameFull, -} - -#[derive(Debug, Serialize)] -#[serde(crate = "calimero_sdk::serde")] -pub enum CommitError { - NotReady, - AlreadyCommitted, - InvalidSignature, -} - -#[derive(Debug, Serialize)] -#[serde(crate = "calimero_sdk::serde")] -pub enum RevealError { - NotReady, - NotCommitted, - InvalidNonce, -} - -#[derive(Debug, Serialize)] -#[serde(crate = "calimero_sdk::serde")] -pub enum ResetError { - NotReady, - InvalidSignature, -} diff --git a/apps/rock-paper-scissors/src/key.rs b/apps/rock-paper-scissors/src/key.rs deleted file mode 100644 index f09175771..000000000 --- a/apps/rock-paper-scissors/src/key.rs +++ /dev/null @@ -1,82 +0,0 @@ -use calimero_sdk::serde::{Deserialize, Serialize}; -use ed25519_dalek::{Signature, SigningKey, VerifyingKey}; - -use crate::commit::Commitment; -use crate::repr::{Repr, ReprBytes}; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(crate = "calimero_sdk::serde")] -pub struct KeyComponents { - pub pk: Repr, - pub sk: Repr, -} - -impl ReprBytes for VerifyingKey { - type Bytes = [u8; 32]; - - fn to_bytes(&self) -> Self::Bytes { - self.to_bytes() - } - - fn from_bytes(f: F) -> Option> - where - F: FnOnce(&mut Self::Bytes) -> Option, - { - let mut bytes = [0; 32]; - if let Some(err) = f(&mut bytes) { - return Some(Err(err)); - } - Some(Ok(VerifyingKey::from_bytes(&bytes).ok()?)) - } -} - -impl ReprBytes for SigningKey { - type Bytes = [u8; 32]; - - fn to_bytes(&self) -> Self::Bytes { - self.to_bytes() - } - - fn from_bytes(f: F) -> Option> - where - F: FnOnce(&mut Self::Bytes) -> Option, - { - let mut bytes = [0; 32]; - - Some(f(&mut bytes).map_or_else(|| Ok(SigningKey::from_bytes(&bytes)), Err)) - } -} - -impl ReprBytes for Signature { - type Bytes = [u8; 64]; - - fn to_bytes(&self) -> Self::Bytes { - self.to_bytes() - } - - fn from_bytes(f: F) -> Option> - where - F: FnOnce(&mut Self::Bytes) -> Option, - { - let mut bytes = [0; 64]; - - Some(f(&mut bytes).map_or_else(|| Ok(Signature::from_bytes(&bytes)), Err)) - } -} - -impl ReprBytes for Commitment { - type Bytes = [u8; 32]; - - fn to_bytes(&self) -> Self::Bytes { - self.to_bytes() - } - - fn from_bytes(f: F) -> Option> - where - F: FnOnce(&mut Self::Bytes) -> Option, - { - let mut bytes = [0; 32]; - - Some(f(&mut bytes).map_or_else(|| Ok(Commitment::from_bytes(&bytes)), Err)) - } -} diff --git a/apps/rock-paper-scissors/src/lib.rs b/apps/rock-paper-scissors/src/lib.rs deleted file mode 100644 index 79b81a937..000000000 --- a/apps/rock-paper-scissors/src/lib.rs +++ /dev/null @@ -1,217 +0,0 @@ -use std::cmp::Ordering; - -use calimero_sdk::app; -use calimero_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use calimero_sdk::serde::{Deserialize, Serialize}; -use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey}; -use rand_chacha::rand_core::SeedableRng; -use rand_chacha::ChaCha20Rng; - -mod choice; -mod commit; -mod errors; -mod key; -mod player_idx; -mod repr; - -use choice::Choice; -use commit::{Commitment, Nonce}; -use errors::{CommitError, JoinError, ResetError, RevealError}; -use key::KeyComponents; -use player_idx::PlayerIdx; -use repr::Repr; - -#[app::state(emits = for<'a> Event<'a>)] -#[derive(Default, Debug, BorshSerialize, BorshDeserialize)] -#[borsh(crate = "calimero_sdk::borsh")] -struct Game { - players: [Option; 2], -} - -#[derive(Default, Debug, BorshSerialize, BorshDeserialize)] -#[borsh(crate = "calimero_sdk::borsh")] -struct Player { - state: Option, - public_key: Repr, - name: String, -} - -#[derive(Debug, Clone, PartialEq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] -#[borsh(crate = "calimero_sdk::borsh")] -#[serde(crate = "calimero_sdk::serde")] -enum State { - Committed(Repr), - Revealed(Choice), -} - -#[app::event] -pub enum Event<'a> { - PlayerCommited { id: PlayerIdx }, - NewPlayer { id: PlayerIdx, name: &'a str }, - PlayerRevealed { id: PlayerIdx, reveal: &'a Choice }, - GameOver { winner: Option }, - StateDumped, -} - -pub type Seed = [u8; 32]; - -#[app::logic] -impl Game { - pub fn create_keypair(seed: Seed) -> KeyComponents { - let mut csprng = ChaCha20Rng::from_seed(seed); - - let keypair = SigningKey::generate(&mut csprng); - - KeyComponents { - pk: Repr::from(keypair.verifying_key()), - sk: Repr::from(keypair), - } - } - - pub fn join( - &mut self, - player_name: String, - public_key: Repr, - ) -> Result { - let Some((index, player)) = self - .players - .iter_mut() - .enumerate() - .find(|(_, player)| player.is_none()) - else { - return Err(JoinError::GameFull); - }; - - app::emit!(Event::NewPlayer { - id: PlayerIdx(index), - name: &player_name - }); - - *player = Some(Player { - state: None, - public_key: Repr::from(public_key), - name: player_name, - }); - - Ok(index) - } - - pub fn state(&self) -> [Option<(&str, &State)>; 2] { - let mut states = [None, None]; - - for (i, player) in self.players.iter().enumerate() { - if let Some(Player { - state: Some(state), - name, - .. - }) = player - { - states[i] = Some((name.as_str(), state)); - } - } - - states - } - - pub fn prepare( - signing_key: Repr, - choice: Choice, - nonce: Nonce, - ) -> (Repr, Repr) { - let commitment = Commitment::of(choice, &nonce); - - let signature = signing_key.sign(commitment.as_ref()); - - (Repr::from(commitment), Repr::from(signature)) - } - - fn players(&mut self, my_idx: PlayerIdx) -> (Option<&mut Player>, Option<&mut Player>) { - let [a, b] = self.players.each_mut(); - if my_idx.is_first() { - return (a.as_mut(), b.as_mut()); - } - (b.as_mut(), a.as_mut()) - } - - pub fn commit( - &mut self, - player_idx: PlayerIdx, - commitment: Repr, - signature: Repr, - ) -> Result<(), CommitError> { - let (Some(player), Some(_)) = self.players(player_idx) else { - return Err(CommitError::NotReady); - }; - - if player.state.is_some() { - return Err(CommitError::AlreadyCommitted); - } - - player - .public_key - .verify(commitment.as_ref(), &signature) - .map_err(|_| CommitError::InvalidSignature)?; - - app::emit!(Event::PlayerCommited { id: player_idx }); - - player.state = Some(State::Committed(commitment)); - - Ok(()) - } - - pub fn reveal(&mut self, player_idx: PlayerIdx, nonce: Nonce) -> Result<(), RevealError> { - let (Some(player), Some(other_player)) = self.players(player_idx) else { - return Err(RevealError::NotReady); - }; - - let Some(State::Committed(commitment)) = &player.state else { - return Err(RevealError::NotCommitted); - }; - - let choice = Choice::determine(commitment, &nonce).ok_or(RevealError::InvalidNonce)?; - - app::emit!(Event::PlayerRevealed { - id: player_idx, - reveal: &choice - }); - - player.state = Some(State::Revealed(choice)); - - if let Some(State::Revealed(other)) = &other_player.state { - match choice.partial_cmp(other) { - Some(Ordering::Less) => app::emit!(Event::GameOver { - winner: Some(player_idx.other()) - }), - Some(Ordering::Equal) => app::emit!(Event::GameOver { winner: None }), - Some(Ordering::Greater) => app::emit!(Event::GameOver { - winner: Some(player_idx) - }), - None => {} - } - } - - Ok(()) - } - - pub fn reset( - &mut self, - player_idx: PlayerIdx, - commitment: Repr, - signature: Repr, - ) -> Result<(), ResetError> { - let (Some(player), _) = self.players(player_idx) else { - return Err(ResetError::NotReady); - }; - - player - .public_key - .verify(commitment.as_ref(), &signature) - .map_err(|_| ResetError::InvalidSignature)?; - - self.players = Default::default(); - - app::emit!(Event::StateDumped); - - Ok(()) - } -} diff --git a/apps/rock-paper-scissors/src/player_idx.rs b/apps/rock-paper-scissors/src/player_idx.rs deleted file mode 100644 index 8ed00bdd4..000000000 --- a/apps/rock-paper-scissors/src/player_idx.rs +++ /dev/null @@ -1,30 +0,0 @@ -use calimero_sdk::serde::{Deserialize, Deserializer, Serialize}; - -#[derive(Copy, Clone, Serialize)] -#[serde(crate = "calimero_sdk::serde")] -pub struct PlayerIdx(pub usize); - -impl PlayerIdx { - pub fn other(&self) -> PlayerIdx { - PlayerIdx(1 - self.0) - } - - pub fn is_first(&self) -> bool { - self.0 == 0 - } -} - -impl<'de> Deserialize<'de> for PlayerIdx { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let value = Deserialize::deserialize(deserializer)?; - match value { - 0 | 1 => Ok(PlayerIdx(value)), - _ => Err(calimero_sdk::serde::de::Error::custom( - "Player index must be 0 or 1", - )), - } - } -} diff --git a/apps/rock-paper-scissors/src/repr.rs b/apps/rock-paper-scissors/src/repr.rs deleted file mode 100644 index e90c5f03f..000000000 --- a/apps/rock-paper-scissors/src/repr.rs +++ /dev/null @@ -1,152 +0,0 @@ -use std::marker::PhantomData; -use std::ops::Deref; -use std::{fmt, io}; - -use bs58::decode::DecodeTarget; -use calimero_sdk::borsh::{BorshDeserialize, BorshSerialize}; -use calimero_sdk::serde::{de, ser, Deserialize, Serialize}; - -#[derive(Eq, Copy, Clone, PartialEq)] -pub enum Bs58 {} - -#[derive(Eq, Copy, Clone, PartialEq)] -pub enum Raw {} - -mod private { - pub trait Sealed {} -} - -pub trait ReprFormat: private::Sealed {} - -impl private::Sealed for Bs58 {} -impl ReprFormat for Bs58 {} - -impl private::Sealed for Raw {} -impl ReprFormat for Raw {} - -#[derive(Eq, Copy, Clone, PartialEq)] -pub struct Repr { - data: T, - _phantom: PhantomData, -} - -pub trait ReprBytes { - type Bytes: AsRef<[u8]>; - - fn to_bytes(&self) -> Self::Bytes; - fn from_bytes(f: F) -> Option> - where - F: FnOnce(&mut Self::Bytes) -> Option, - Self: Sized; -} - -impl From for Repr { - fn from(data: T) -> Self { - Repr { - data, - _phantom: PhantomData, - } - } -} - -impl From> for Repr { - fn from(repr: Repr) -> Self { - Repr { - data: repr.data, - _phantom: PhantomData, - } - } -} - -impl Deref for Repr { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.data - } -} - -impl Default for Repr { - fn default() -> Self { - Repr::from(T::default()) - } -} - -impl fmt::Debug for Repr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.data.fmt(f) - } -} - -impl Serialize for Repr { - fn serialize(&self, serializer: S) -> Result - where - S: ser::Serializer, - { - let bytes = self.data.to_bytes(); - let encoded = bs58::encode(bytes).into_string(); - serializer.serialize_str(&encoded) - } -} - -impl<'de, T: ReprBytes> Deserialize<'de> for Repr -where - T::Bytes: DecodeTarget, -{ - fn deserialize(deserializer: D) -> Result - where - D: de::Deserializer<'de>, - { - let encoded = ::deserialize(deserializer)?; - - let data = match T::from_bytes(|bytes| bs58::decode(&encoded).onto(bytes).err()) { - Some(data) => data.map_err(de::Error::custom)?, - None => return Err(de::Error::custom("Invalid key")), - }; - - Ok(Repr::from(data)) - } -} - -impl BorshSerialize for Repr -where - T::Bytes: BorshSerialize, -{ - fn serialize(&self, writer: &mut W) -> Result<(), io::Error> { - self.data.to_bytes().serialize(writer) - } -} - -impl BorshDeserialize for Repr -where - T::Bytes: BorshDeserialize, -{ - fn deserialize_reader(reader: &mut R) -> io::Result { - let bytes = T::Bytes::deserialize_reader(reader)?; - - let data = match T::from_bytes(|data| { - *data = bytes; - - None::<()> - }) { - Some(data) => unsafe { data.unwrap_unchecked() }, - None => return Err(io::ErrorKind::InvalidData.into()), - }; - - Ok(Repr::from(data)) - } -} - -impl BorshSerialize for Repr { - fn serialize(&self, writer: &mut W) -> Result<(), io::Error> { - self.data.serialize(writer) - } -} - -impl BorshDeserialize for Repr { - fn deserialize_reader(reader: &mut R) -> io::Result { - let data = T::deserialize_reader(reader)?; - - Ok(Repr::from(data)) - } -} diff --git a/contracts/leaderboard/Cargo.toml b/contracts/leaderboard/Cargo.toml deleted file mode 100644 index c95134d3d..000000000 --- a/contracts/leaderboard/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "leaderboard" -description = "leaderboard" -version = "0.1.0" -authors.workspace = true -edition.workspace = true -repository.workspace = true -license.workspace = true - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -near-sdk.workspace = true - -[dev-dependencies] -near-sdk = { workspace = true, features = ["unit-testing"] } -tokio.workspace = true -near-workspaces.workspace = true -serde_json.workspace = true diff --git a/contracts/leaderboard/build.sh b/contracts/leaderboard/build.sh deleted file mode 100755 index b088a17bd..000000000 --- a/contracts/leaderboard/build.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -rustup target add wasm32-unknown-unknown -set -e - -cd "$(dirname $0)" - -TARGET="${CARGO_TARGET_DIR:-../../target}" - -cargo build --target wasm32-unknown-unknown --profile app-release - -mkdir -p res - -cp $TARGET/wasm32-unknown-unknown/app-release/leaderboard.wasm ./res/ - -if command -v wasm-opt > /dev/null; then - wasm-opt -Oz ./res/leaderboard.wasm -o ./res/leaderboard.wasm -fi diff --git a/contracts/leaderboard/relayer/mock-ws-server.js b/contracts/leaderboard/relayer/mock-ws-server.js deleted file mode 100644 index 261d09a78..000000000 --- a/contracts/leaderboard/relayer/mock-ws-server.js +++ /dev/null @@ -1,41 +0,0 @@ -const { WebSocketServer } = require('ws'); -const prompt = require('prompt-sync')({ sigint: true }); - -const wss = new WebSocketServer({ port: 8080 }); - -console.log('Waiting for a new connection...'); - -wss.on('connection', function connection(ws) { - let keepAsking = true; - ws.on('error', () => keepAsking = false); - - ws.on('message', function message(data) { - console.log('received: %s', data); - }); - - while (keepAsking) { - console.log('-'.repeat(process.stdout.columns)); - const action = prompt('What to do? add-score/get-score: '); - if (action === 'add-score') { - const account = prompt('Account: '); - const app = prompt('Application: '); - const score = parseInt(prompt('score: ')); - ws.send(JSON.stringify({ - action: 'add-score', - app, - account, - score - })); - } else if (action === 'get-score') { - const account = prompt('Account: '); - const app = prompt('Application: '); - ws.send(JSON.stringify({ - action: 'get-score', - app, - account, - })); - } else { - ws.close(); - } - } -}); diff --git a/contracts/leaderboard/relayer/package.json b/contracts/leaderboard/relayer/package.json deleted file mode 100644 index b9144b499..000000000 --- a/contracts/leaderboard/relayer/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "relayer", - "version": "1.0.0", - "main": "index.js", - "author": "Saeed", - "license": "MIT", - "dependencies": { - "command-line-args": "^5.2.1", - "near-api-js": "^4.0.1", - "prompt-sync": "^4.2.0", - "ws": "^8.17.1" - } -} diff --git a/contracts/leaderboard/relayer/relayer.js b/contracts/leaderboard/relayer/relayer.js deleted file mode 100644 index 9f4eba59f..000000000 --- a/contracts/leaderboard/relayer/relayer.js +++ /dev/null @@ -1,149 +0,0 @@ -const nearAPI = require('near-api-js'); -const fs = require('fs'); -const commandLineArgs = require('command-line-args'); -const GameEventListener = require('./ws'); - -const { Contract } = nearAPI; - -const createKeyStore = async () => { - const { KeyPair, keyStores } = nearAPI; - - const ACCOUNT_ID = 'highfalutin-act.testnet'; - const NETWORK_ID = 'testnet'; - const KEY_PATH = - '/home/saeed/.near-credentials/testnet/highfalutin-act.testnet.json'; - - const credentials = JSON.parse(fs.readFileSync(KEY_PATH)); - const myKeyStore = new keyStores.InMemoryKeyStore(); - myKeyStore.setKey( - NETWORK_ID, - ACCOUNT_ID, - KeyPair.fromString(credentials.private_key) - ); - - return myKeyStore; -}; - -let keyStore; -const connectToNear = async () => { - keyStore = await createKeyStore(); - const connectionConfig = { - networkId: 'testnet', - keyStore, - nodeUrl: 'https://rpc.testnet.near.org', - walletUrl: 'https://testnet.mynearwallet.com/', - helperUrl: 'https://helper.testnet.near.org', - explorerUrl: 'https://testnet.nearblocks.io', - }; - const { connect } = nearAPI; - const nearConnection = await connect(connectionConfig); - return nearConnection; -}; - -const addScore = async (account_id, app_name, score) => { - if (contract === null) { - throw new Error('Contract is not initialized'); - } - - const account = await near.account('highfalutin-act.testnet'); - await contract.add_score({ - signerAccount: account, - args: { - app_name, - account_id, - score, - }, - }); -}; - -const getScore = async (account_id, app_name) => { - if (contract === null) { - throw new Error('Contract is not initialized'); - } - - return await contract.get_score({ - app_name, - account_id, - }); -}; - -const getScores = async (app_name) => { - if (contract === null) { - throw new Error('Contract is not initialized'); - } - - return await contract.get_scores({ - app_name, - }); -}; - -let contract = null; -let near = null; - -async function main() { - const optionDefinitions = [ - { name: 'subscribe', type: Boolean }, - { name: 'add-score', type: Boolean }, - { name: 'get-score', type: Boolean }, - { name: 'get-scores', type: Boolean }, - { name: 'account', type: String }, - { name: 'score', type: Number }, - { name: 'app', type: String }, - { name: 'applicationId', type: String }, - { name: 'nodeUrl', type: String }, - ]; - - const options = commandLineArgs(optionDefinitions); - - const nearConnection = await connectToNear(); - near = nearConnection; - contract = new Contract( - nearConnection.connection, - 'highfalutin-act.testnet', - { - changeMethods: ['add_score'], - viewMethods: ['get_version', 'get_score', 'get_scores'], - } - ); - if (options.subscribe) { - const { applicationId, nodeUrl } = options; - console.log(`Subscribed for the events of ${applicationId}`); - subscribe(applicationId, nodeUrl); - } else if (options['add-score']) { - const { account, app, score } = options; - await addScore(account, app, score); - console.log( - `Score added for account: ${account}, app: ${app}, score: ${score}` - ); - } else if (options['get-score']) { - const { account, app } = options; - const score = await getScore(account, app); - console.log(`${account} score is: ${score}`); - } else if (options['get-scores']) { - const { app } = options; - const scores = await getScores(app); - console.log(`Scores for ${app}: ${JSON.stringify(scores)}`); - } -} - -let eventListener; -let players = {}; -const subscribe = (applicationId, nodeUrl) => { - eventListener = new GameEventListener(nodeUrl, applicationId); - eventListener.on('NewPlayer', (player) => { - players[player.id] = player.name; - }); - - eventListener.on('GameOver', (winner) => { - addScore(players[winner.winner], 'rsp', 1000).then(() => - console.log(`Score added for ${players[winner.winner]}`) - ).catch(e => { - console.error(`Failed to add the score. ${e}`); - }); - }); -}; - -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/contracts/leaderboard/relayer/ws.js b/contracts/leaderboard/relayer/ws.js deleted file mode 100644 index 334e52c75..000000000 --- a/contracts/leaderboard/relayer/ws.js +++ /dev/null @@ -1,50 +0,0 @@ - -// Listen for messages -const WebSocket = require('ws'); - -module.exports = class GameEventListener { - constructor(nodeUrl, applicationId) { - this.ws = new WebSocket(`${nodeUrl}/ws`); - this.ws.on('open', () => { - const request = { - id: this.getRandomRequestId(), - method: 'subscribe', - params: { - applicationIds: [applicationId], - }, - }; - this.ws.send(JSON.stringify(request)); - }); - - this.events = {}; - this.ws.on('message', async (event) => { - const utf8Decoder = new TextDecoder('UTF-8'); - const data = utf8Decoder.decode(event); - await this.parseMessage(data); - }); - } - - on(event, func) { - this.events[event] = func; - } - - parseMessage(msg) { - try { - const event = JSON.parse(msg); - for (const e of event.result.data.events) { - if (e.kind in this.events) { - let bytes = new Int8Array(e.data); - let str = new TextDecoder().decode(bytes); - this.events[e.kind](JSON.parse(str)); - } - } - } catch (e) { - console.error(`Failed to parse the json: ${e}`); - } - } - - getRandomRequestId() { - return Math.floor(Math.random() * Math.pow(2, 32)); - } -}; - diff --git a/contracts/leaderboard/relayer/yarn.lock b/contracts/leaderboard/relayer/yarn.lock deleted file mode 100644 index b2338b7b4..000000000 --- a/contracts/leaderboard/relayer/yarn.lock +++ /dev/null @@ -1,379 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@near-js/accounts@1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@near-js/accounts/-/accounts-1.2.0.tgz#d0ffe0ddd976c04b0f27122d4bd737202fb82747" - integrity sha512-0D/Tl7i2rqqVydGwu9zWBFOk6P7t4Zs2Gfo7l+8jNjOoioYsH/YCWaOheoH7SVu4wQ3xP9YEyjvZ8JL6xzYyHA== - dependencies: - "@near-js/crypto" "1.2.3" - "@near-js/providers" "0.2.1" - "@near-js/signers" "0.1.3" - "@near-js/transactions" "1.2.1" - "@near-js/types" "0.2.0" - "@near-js/utils" "0.2.1" - borsh "1.0.0" - depd "2.0.0" - is-my-json-valid "^2.20.6" - lru_map "0.4.1" - near-abi "0.1.1" - -"@near-js/crypto@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@near-js/crypto/-/crypto-1.2.3.tgz#ba318d77b9eed79ef92a86f7a2c84562cb2f6b9d" - integrity sha512-BuNE+tdcxwImxktFtuAxLiVejFDtn1X92kejcDcYc6f7e0ku9yMntdw98LMb+5ls+xlRuF1UDoi/hUF1LPVpyQ== - dependencies: - "@near-js/types" "0.2.0" - "@near-js/utils" "0.2.1" - "@noble/curves" "1.2.0" - borsh "1.0.0" - randombytes "2.1.0" - -"@near-js/keystores-browser@0.0.11": - version "0.0.11" - resolved "https://registry.yarnpkg.com/@near-js/keystores-browser/-/keystores-browser-0.0.11.tgz#dc0dab662fb2045f978fe1c725f03f0fd11f8267" - integrity sha512-AQ86ST+keKjM5iektKLXu3q94lN8pG6R/LXVoIgm5/hi63n2QzhAd0XlUj9fcyPrfoGOckwUu6pFtXPbveBypw== - dependencies: - "@near-js/crypto" "1.2.3" - "@near-js/keystores" "0.0.11" - -"@near-js/keystores-node@0.0.11": - version "0.0.11" - resolved "https://registry.yarnpkg.com/@near-js/keystores-node/-/keystores-node-0.0.11.tgz#b711c6fc0451d4115936734690e08de51e440ef4" - integrity sha512-KeBl7oL8AwUwTilYPV3apEcL1P+UMAGJQvmkEFl9lyK7mftyjogehdqjqFREAdQpR+4jX5NXvU8ZJIShebK3ZA== - dependencies: - "@near-js/crypto" "1.2.3" - "@near-js/keystores" "0.0.11" - -"@near-js/keystores@0.0.11": - version "0.0.11" - resolved "https://registry.yarnpkg.com/@near-js/keystores/-/keystores-0.0.11.tgz#570c70c4c5bb6ba64a94b8bff4cc71cc23265aec" - integrity sha512-B/VkSNIT8vxMozDbK9O54YQGa4JT/rFnB0W+0cN3na38sQHdvzK015X2RHK8mfS0isP/iIT9QzIQtYZcI3M83Q== - dependencies: - "@near-js/crypto" "1.2.3" - "@near-js/types" "0.2.0" - -"@near-js/providers@0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@near-js/providers/-/providers-0.2.1.tgz#1d195638b07fd542e202a61dd8c571034ec7cd62" - integrity sha512-F5ZVlXynGopg3BjK3ihyA28tnOk/cM7kUhc/bw5aJg+m+oa1yuBkaAp9JbihagbLZpWOZiDJmkrdkpvTvQlHag== - dependencies: - "@near-js/transactions" "1.2.1" - "@near-js/types" "0.2.0" - "@near-js/utils" "0.2.1" - borsh "1.0.0" - http-errors "1.7.2" - optionalDependencies: - node-fetch "2.6.7" - -"@near-js/signers@0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@near-js/signers/-/signers-0.1.3.tgz#7ac9c630536457c3cd94c4faf901b7033a76b6bc" - integrity sha512-Eim6ZsQUgsaSzi+oyR9cQesOO2QcZmhK+tawZan1vni8y+JvKnSH6r3krzbtvKWqIlx/kJ+PsIV74YIxPY5Uhw== - dependencies: - "@near-js/crypto" "1.2.3" - "@near-js/keystores" "0.0.11" - "@noble/hashes" "1.3.3" - -"@near-js/transactions@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@near-js/transactions/-/transactions-1.2.1.tgz#f9a304cd2a35f292557c3764473127b231c06892" - integrity sha512-w2EXgTRXJ+Zxqh8lVnQuRnpCEm6Cq7NxqAcfH6x0BPuSXye5kR9d0n2ut8AGkSXWeooKKEUnDhi6UcXadfoerg== - dependencies: - "@near-js/crypto" "1.2.3" - "@near-js/signers" "0.1.3" - "@near-js/types" "0.2.0" - "@near-js/utils" "0.2.1" - "@noble/hashes" "1.3.3" - borsh "1.0.0" - -"@near-js/types@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@near-js/types/-/types-0.2.0.tgz#5370c3e9230103222b2827dbd6370f03c4e996d1" - integrity sha512-pTahjni0+PzStseFtnnI9nqmh+ZrHqBqeERo3B3OCXUC/qEie0ZSBMSMt80SgqnaGAy5/CqkCLO9zOx1gA8Cwg== - -"@near-js/utils@0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@near-js/utils/-/utils-0.2.1.tgz#6798cf8c3a6ed8057da002401e24409c49454a82" - integrity sha512-u7yR1fmxIcYoiITR1spTvqciXbMXNvlrmRcneNt9DWeQP7yPdbCQtRB7lMN2KI7ONkUf3U7xiheQDDmk2vFI0w== - dependencies: - "@near-js/types" "0.2.0" - bs58 "4.0.0" - depd "2.0.0" - mustache "4.0.0" - -"@near-js/wallet-account@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@near-js/wallet-account/-/wallet-account-1.2.1.tgz#f94ebd9c0e58e437045e17467c283d692c3ad6e4" - integrity sha512-T1k15LN9YIgz1Ca3u76GFxtyDSSKNeBTqEKOJZiOMPse9HjXeiI/ycrOVzmEG/a+ZJ5tipQwcDDChUsY4nTQ1w== - dependencies: - "@near-js/accounts" "1.2.0" - "@near-js/crypto" "1.2.3" - "@near-js/keystores" "0.0.11" - "@near-js/providers" "0.2.1" - "@near-js/signers" "0.1.3" - "@near-js/transactions" "1.2.1" - "@near-js/types" "0.2.0" - "@near-js/utils" "0.2.1" - borsh "1.0.0" - -"@noble/curves@1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" - integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== - dependencies: - "@noble/hashes" "1.3.2" - -"@noble/hashes@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" - integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== - -"@noble/hashes@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" - integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== - -"@types/json-schema@^7.0.11": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - -array-back@^3.0.1, array-back@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" - integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== - -base-x@^2.0.1: - version "2.0.6" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-2.0.6.tgz#4582a91ebcec99ee06f4e4032030b0cf1c2941d8" - integrity sha512-UAmjxz9KbK+YIi66xej+pZVo/vxUOh49ubEvZW5egCbxhur05pBb+hwuireQwKO4nDpsNm64/jEei17LEpsr5g== - dependencies: - safe-buffer "^5.0.1" - -borsh@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/borsh/-/borsh-1.0.0.tgz#b564c8cc8f7a91e3772b9aef9e07f62b84213c1f" - integrity sha512-fSVWzzemnyfF89EPwlUNsrS5swF5CrtiN4e+h0/lLf4dz2he4L3ndM20PS9wj7ICSkXJe/TQUHdaPTq15b1mNQ== - -bs58@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.0.tgz#65f5deaf6d74e6135a99f763ca6209ab424b9172" - integrity sha512-/jcGuUuSebyxwLLfKrbKnCJttxRf9PM51EnHTwmFKBxl4z1SGkoAhrfd6uZKE0dcjQTfm6XzTP8DPr1tzE4KIw== - dependencies: - base-x "^2.0.1" - -command-line-args@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" - integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== - dependencies: - array-back "^3.1.0" - find-replace "^3.0.0" - lodash.camelcase "^4.3.0" - typical "^4.0.0" - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== - -find-replace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" - integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== - dependencies: - array-back "^3.0.1" - -generate-function@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" - integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== - dependencies: - is-property "^1.0.2" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - integrity sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ== - dependencies: - is-property "^1.0.0" - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== - -is-my-ip-valid@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz#f7220d1146257c98672e6fba097a9f3f2d348442" - integrity sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg== - -is-my-json-valid@^2.20.6: - version "2.20.6" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz#a9d89e56a36493c77bda1440d69ae0dc46a08387" - integrity sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw== - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^5.0.0" - xtend "^4.0.0" - -is-property@^1.0.0, is-property@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g== - -jsonpointer@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" - integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -lru_map@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.4.1.tgz#f7b4046283c79fb7370c36f8fca6aee4324b0a98" - integrity sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg== - -mustache@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.0.0.tgz#7f02465dbb5b435859d154831c032acdfbbefb31" - integrity sha512-FJgjyX/IVkbXBXYUwH+OYwQKqWpFPLaLVESd70yHjSDunwzV2hZOoTBvPf4KLoxesUzzyfTH6F784Uqd7Wm5yA== - -near-abi@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/near-abi/-/near-abi-0.1.1.tgz#b7ead408ca4ad11de4fe3e595d30a7a8bc5307e0" - integrity sha512-RVDI8O+KVxRpC3KycJ1bpfVj9Zv+xvq9PlW1yIFl46GhrnLw83/72HqHGjGDjQ8DtltkcpSjY9X3YIGZ+1QyzQ== - dependencies: - "@types/json-schema" "^7.0.11" - -near-api-js@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/near-api-js/-/near-api-js-4.0.1.tgz#ac99ef0fc11f24a733ba9c93bd7f094311f891dd" - integrity sha512-lBLgxhXhY7M05UI0ppBOzfArkMCXRvtKiHVgpxrSqN/mp3WCcWV5C+Y/dwx9U6JtaNG8UWxrvB8kHqKyWGeisw== - dependencies: - "@near-js/accounts" "1.2.0" - "@near-js/crypto" "1.2.3" - "@near-js/keystores" "0.0.11" - "@near-js/keystores-browser" "0.0.11" - "@near-js/keystores-node" "0.0.11" - "@near-js/providers" "0.2.1" - "@near-js/signers" "0.1.3" - "@near-js/transactions" "1.2.1" - "@near-js/types" "0.2.0" - "@near-js/utils" "0.2.1" - "@near-js/wallet-account" "1.2.1" - "@noble/curves" "1.2.0" - borsh "1.0.0" - depd "2.0.0" - http-errors "1.7.2" - near-abi "0.1.1" - node-fetch "2.6.7" - -node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -prompt-sync@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/prompt-sync/-/prompt-sync-4.2.0.tgz#0198f73c5b70e3b03e4b9033a50540a7c9a1d7f4" - integrity sha512-BuEzzc5zptP5LsgV5MZETjDaKSWfchl5U9Luiu8SKp7iZWD5tZalOxvNcZRwv+d2phNFr8xlbxmFNcRKfJOzJw== - dependencies: - strip-ansi "^5.0.0" - -randombytes@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -safe-buffer@^5.0.1, safe-buffer@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -"statuses@>= 1.5.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - -strip-ansi@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -typical@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" - integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -ws@^8.17.1: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" - integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== diff --git a/contracts/leaderboard/src/lib.rs b/contracts/leaderboard/src/lib.rs deleted file mode 100644 index 745f4a2d7..000000000 --- a/contracts/leaderboard/src/lib.rs +++ /dev/null @@ -1,85 +0,0 @@ -use std::collections::BTreeMap; - -use near_sdk::json_types::U128; -use near_sdk::near; -use near_sdk::store::{LookupMap, UnorderedMap}; - -type UserName = String; - -#[near(contract_state)] -pub struct LeaderBoard { - scores: LookupMap>, // Key is app name, value is the leaderboard itself -} - -impl Default for LeaderBoard { - fn default() -> Self { - Self { - scores: LookupMap::new(b"m"), - } - } -} - -#[near] -impl LeaderBoard { - pub fn add_score(&mut self, app_name: String, account_id: UserName, score: U128) { - let app_leaderboard = self - .scores - .entry(app_name.clone()) - .or_insert_with(|| UnorderedMap::new(app_name.as_bytes())); - - let new_score = app_leaderboard.entry(account_id.clone()).or_default().0 + score.0; - app_leaderboard.insert(account_id, U128(new_score)); - } - - pub fn get_score(&self, app_name: String, account_id: UserName) -> Option { - self.scores - .get(&app_name)? - .get(&account_id) - .map(|score| score.clone()) - } - - pub fn get_scores(&self, app_name: String) -> Option> { - let mut map = BTreeMap::new(); - for (k, v) in self.scores.get(&app_name)? { - map.insert(k.to_string(), v.0); - } - Some(map) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn add_score() { - let mut leader_board = LeaderBoard::default(); - let account = "alice.testnet".to_string(); - leader_board.add_score("test_app".to_string(), account.clone(), U128(10)); - - let score = leader_board.get_score("test_app".to_string(), account); - assert_eq!(score, Some(U128(10))); - } - - #[test] - fn get_score_of_absent_account() { - let mut leader_board = LeaderBoard::default(); - let account = "alice.testnet".to_string(); - leader_board.add_score("test_app".to_string(), account.clone(), U128(10)); - - let bob_account = "bob.testnet".to_string(); - - let score = leader_board.get_score("test_app".to_string(), bob_account); - assert_eq!(score, None); - } - - #[test] - fn get_score_of_absent_app() { - let mut leader_board = LeaderBoard::default(); - let account = "alice.testnet".to_string(); - leader_board.add_score("test_app".to_string(), account.clone(), U128(10)); - - let score = leader_board.get_score("test_app_2".to_string(), account); - assert_eq!(score, None); - } -} diff --git a/contracts/leaderboard/tests/sandbox.rs b/contracts/leaderboard/tests/sandbox.rs deleted file mode 100644 index df615cf5b..000000000 --- a/contracts/leaderboard/tests/sandbox.rs +++ /dev/null @@ -1,66 +0,0 @@ -use near_sdk::json_types::U128; -use near_sdk::NearToken; -use serde_json::json; - -#[tokio::test] -async fn test_score_board_contract() -> Result<(), Box> { - let sandbox = near_workspaces::sandbox().await?; - let wasm = tokio::fs::read("res/leaderboard.wasm").await?; - - let contract = sandbox.dev_deploy(&wasm).await?; - - let alice_account = sandbox.dev_create_account().await?; - let bob_account = sandbox.dev_create_account().await?; - - let alice_outcome = alice_account - .call(contract.id(), "add_score") - .args_json(json!({"app_name": "test_app", "account_id": alice_account.id(), "score": "10"})) - .deposit(NearToken::from_near(0)) - .transact() - .await?; - - assert!(alice_outcome.is_success()); - - let score: Option = contract - .view("get_score") - .args_json(json!({"app_name": "test_app", "account_id": alice_account.id()})) - .await? - .json()?; - - assert_eq!(score, Some(U128(10))); - - let score: Option = contract - .view("get_score") - .args_json(json!({"app_name": "test_app", "account_id": bob_account.id()})) - .await? - .json()?; - - assert_eq!(score, None); - - let alice_outcome = alice_account - .call(contract.id(), "add_score") - .args_json( - json!({"app_name": "test_app_2", "account_id": alice_account.id(), "score": "100"}), - ) - .deposit(NearToken::from_near(0)) - .transact() - .await?; - - assert!(alice_outcome.is_success()); - - let score: Option = contract - .view("get_score") - .args_json(json!({"app_name": "test_app", "account_id": alice_account.id()})) - .await? - .json()?; - assert_eq!(score, Some(U128(10))); - - let score: Option = contract - .view("get_score") - .args_json(json!({"app_name": "test_app_2", "account_id": alice_account.id()})) - .await? - .json()?; - assert_eq!(score, Some(U128(100))); - - Ok(()) -}