Skip to content

Commit

Permalink
Add EXT NFT standard code
Browse files Browse the repository at this point in the history
  • Loading branch information
patnorris authored and patnorris committed Oct 17, 2023
1 parent bbe6a6b commit 2a7a5f9
Show file tree
Hide file tree
Showing 5 changed files with 484 additions and 0 deletions.
18 changes: 18 additions & 0 deletions notes/DevelopmentNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,22 @@ Space Neighbors local testing with dummy entities:
};
spaceNeighborsResponse = [dummyTestEntity1, dummyTestEntity2, dummyTestEntity3, dummyTestEntity4]; */
```

NFT related calls:
dfx canister --network ic call PersonalWebSpace_backend metadata "(\"yxqhi-2ikor-uwiaa-aaaaa-caat4-yaqca-aaaaa-a\")"

dfx canister --network ic call PersonalWebSpace_backend tokens "(\"cda4n-7jjpo-s4eus-yjvy7-o6qjc-vrueo-xd2hh-lh5v2-k7fpf-hwu5o-yqe\")"

dfx canister --network ic call PersonalWebSpace_backend balance "(\"cda4n-7jjpo-s4eus-yjvy7-o6qjc-vrueo-xd2hh-lh5v2-k7fpf-hwu5o-yqe\")"

dfx canister --network ic call PersonalWebSpace_backend http_request "(
record {
body = vec { };
headers = vec { };
method = \"\";
url = \"tokenid=yxqhi-2ikor-uwiaa-aaaaa-caat4-yaqca-aaaaa-a\";
}
)"

dfx canister --network ic call PersonalWebSpace_backend createSpace "(\"<html> <head> <script src="https://aframe.io/releases/1.4.2/aframe.min.js"></script> <script src="//cdn.rawgit.com/donmccurdy/aframe-extras/v3.8.3/dist/aframe-extras.min.js"></script> <script src="https://mannymeadows.github.io/Noosa/aframe-sun-sky.min.js"></script> </head> <body> <a-scene cursor="rayOrigin: mouse" gltf-model="dracoDecoderPath: https://www.gstatic.com/draco/v1/decoders/;" inspector="" keyboard-shortcuts="" screenshot="" vr-mode-ui="" device-orientation-permission-ui="" raycaster="direction: 0.9544506796854287 -0.10164039183312146 -0.2805229594810959; origin: -4.846717797159805 5.074580504821491 2.3289351396596443; useWorldCoordinates: true"> <a-assets> <a-asset-item id="island-glb" src="tropical_island_modified.glb"></a-asset-item> <a-asset-item id="sunbed-glb" src="at_a_beach_modified.glb"></a-asset-item> </a-assets> <a-entity camera="active: true" look-controls wasd-controls="acceleration:65; fly:true" position="0 4.6 0"></a-entity> <a-light type="directional" intensity="0.9" position="-1 -2 2" light=""></a-light> <a-light type="directional" intensity="1.0" position="2 1 -1" light=""></a-light> <a-entity environment="preset: arches" position="7 -7 -9" ></a-entity> <a-ocean color="#92E2E2" width="350" depth="250" density="150" speed="2" opacity="0.5"></a-ocean> <a-entity gltf-model="#island-glb" scale="1 1 1" position="0 3 -5" id="Island" animation-mixer></a-entity> <div class="a-loader-title" style="display: none;"></div> <div class="a-loader-title" style="display: none;"></div><div class="a-loader-title" style="display: none;"></div><div class="a-loader-title" style="display: none;"></div><div class="a-loader-title" style="display: none;"></div><div class="a-loader-title" style="display: none;"></div></a-scene> </body> </html>\")"
167 changes: 167 additions & 0 deletions src/PersonalWebSpace_backend/main.mo
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ import Random "mo:base/Random";
import RBTree "mo:base/RBTree";
import HashMap "mo:base/HashMap";
import Array "mo:base/Array";
import Result "mo:base/Result";

import FileTypes "./types/FileStorageTypes";
import Utils "./Utils";

import Types "./Types";
import HTTP "./Http";

import ExtCore "./EXT/Core";
import ExtCommon "./EXT/Common";
import ExtNonFungible "./EXT/NonFungible";
import Stoic "./EXT/Stoic";

import Protocol "./Protocol";
Expand Down Expand Up @@ -1216,6 +1220,169 @@ public shared(msg) func deleteFile(fileId: Text) : async FileTypes.FileResult {
return false;
};

// EXT standard: https://github.com/Toniq-Labs/extendable-token#:~:text=EXT%20Standard%20allows%20for%20the,(e.g.%20similar%20to%20transferAndCall%20).
type AccountIdentifier = ExtCore.AccountIdentifier;
type Balance = ExtCore.Balance;
type TokenIdentifier = ExtCore.TokenIdentifier;
type Extension = ExtCore.Extension;
type CommonError = ExtCore.CommonError;
type BalanceRequest = ExtCore.BalanceRequest;
type BalanceResponse = ExtCore.BalanceResponse;
type TransferRequest = ExtCore.TransferRequest;
type TransferResponse = ExtCore.TransferResponse;
type ExtMetadata = ExtCommon.Metadata;
type ExtMintRequest = ExtNonFungible.MintRequest;

public shared(msg) func transfer(request: TransferRequest) : async TransferResponse {
let from : Principal = switch(request.from) {
case (#address address) {
return #err(#Other "request.from needs to be Principal");
};
case (#principal principal) { principal };
};
let to: Principal = switch(request.to) {
case (#address address) {
return #err(#Other "request.to needs to be Principal");
};
case (#principal principal) { principal };
};
let token_id: Types.TokenId = textToNat64(request.token);
let transferReceipt : Types.TxReceipt = transferFrom(from, to, token_id, msg.caller);
let userBalance = List.size(
List.filter(nfts, func(token: Types.Nft) : Bool { token.owner == from })
);
return #ok(userBalance);
};

private let EXTENSIONS : [Extension] = ["@ext/common", "@ext/nonfungible"];
public query func extensions() : async [Extension] {
EXTENSIONS;
};

public query func balance(request : BalanceRequest) : async BalanceResponse {
let userPrincipal : Principal = switch(request.user) {
case (#address address) {
return #err(#Other "request.user needs to be Principal");
};
case (#principal principal) { principal };
};
let userBalance = List.size(
List.filter(nfts, func(token: Types.Nft) : Bool { token.owner == userPrincipal })
);
return #ok(userBalance);
//return #Ok(Nat64.toNat(userBalance)); // convert Nat64 to Nat
/* let aid = ExtCore.User.toAID(request.user);
switch (_balances.get(aid)) {
case (?balance) {
return #ok(balance);
};
case (_) {
return #ok(0);
};
} */
};

private stable let _supply : Balance = Nat16.toNat(maxLimit);
public query func supply(token : TokenIdentifier) : async Result.Result<Balance, CommonError> {
#ok(_supply);
};

public query func metadata(token : TokenIdentifier) : async Result.Result<ExtMetadata, CommonError> {
let tokenIdExt : Nat32 = ExtCore.TokenIdentifier.getIndex(token);
switch (List.get(nfts, Nat32.toNat(tokenIdExt))) {
case (?nft) {
let md : ExtMetadata = #nonfungible({
metadata = ?nft.metadata[0].data;
});
return #ok(md);
};
case (_) {
return #err(#InvalidToken(token));
};
};
};

// Ext nonfungible

public shared query func bearer (token : TokenIdentifier) : async Result.Result<AccountIdentifier, CommonError> {
if (not ExtCore.TokenIdentifier.isPrincipal(token, Principal.fromActor(Self))) {
return #err(#InvalidToken(token));
};
let tokenIdExt : Nat32 = ExtCore.TokenIdentifier.getIndex(token);
switch (List.get(nfts, Nat32.toNat(tokenIdExt))) {
case (?nft) {
let ownerAID = ExtCore.User.toAID(#principal(nft.owner));
return #ok(ownerAID);
};
case (_) {
return #err(#InvalidToken(token));
};
};
};

public shared({ caller }) func mintNFT (request : ExtMintRequest) : async () {
let recipient = ExtCore.User.toAID(request.to);
};

// Stoic Wallet integration

func getTokensForStoic(caller : Principal, accountId : AccountIdentifier) : Result.Result<[ExtCore.TokenIndex], CommonError> {
/* let userPrincipal : Principal = switch(accountId) {
case (#address address) {
return #err(#Other "accountId needs to be Principal");
};
case (#principal principal) { principal };
}; */
let items = List.filter(nfts, func(token: Types.Nft) : Bool { ExtCore.User.toAID(#principal(token.owner)) == accountId });
let tokenIds = List.map(items, func (item : Types.Nft) : ExtCore.TokenIndex { Nat32.fromNat(Nat64.toNat(item.id)) });
return #ok(List.toArray(tokenIds));
/* var tokens : [Ext.TokenIndex] = [];
var i : Nat32 = 0;
for (token in Iter.fromArray(state._Tokens.read(null))) {
switch (token) {
case (?t) {
if (Ext.AccountIdentifier.equal(accountId, t.owner)) {
tokens := Array.append(tokens, [i]);
};
};
case _ ();
};
i += 1;
};
#ok(tokens); */
};

public query ({ caller }) func tokens (accountId : AccountIdentifier) : async Result.Result<[ExtCore.TokenIndex], CommonError> {
getTokensForStoic(caller, accountId);
};

public type EntrepotTypesListing = {
// 6 extra digits
// javascript : 1_637_174_793_714
// motoko : 1_637_174_793_714_948_574
locked : ?Time.Time;
price : Nat64; // ICPe8
seller : Principal;
subaccount : ?ExtCore.SubAccount;
};

public query ({ caller }) func tokens_ext(accountId : AccountIdentifier) : async Result.Result<[(ExtCore.TokenIndex, ?EntrepotTypesListing, ?[Nat8])], CommonError> {
let items = List.filter(nfts, func(token: Types.Nft) : Bool { ExtCore.User.toAID(#principal(token.owner)) == accountId });
let tokenIds = List.map(items, func (item : Types.Nft) : ExtCore.TokenIndex { Nat32.fromNat(Nat64.toNat(item.id)) });

let tokens = Buffer.Buffer<(ExtCore.TokenIndex, ?EntrepotTypesListing, ?[Nat8])>(0);
//var i : Nat32 = 0;
for (tokenId in Iter.fromList(tokenIds)) {
tokens.add((
tokenId,
null,
null,
));
//i += 1;
};
#ok(tokens.toArray());
};

// Upgrade Hooks
system func preupgrade() {
fileDatabaseStable := Iter.toArray(fileDatabase.entries());
Expand Down
Loading

0 comments on commit 2a7a5f9

Please sign in to comment.