own your data, empower your world
In times when people need it the most, the first use case for Tyron self-sovereign identities will be peer-to-peer donations - help your community!
A react native decentralized app, pung.me is a prototype that allows your digital identity to send Xfers's $XSGD to another 'domain.did' with no transaction fee, paying only for Zilliqa gas.
Donation campaign codes, e.g. 'covid-aid', get registered in your DID contract with a duration of 1 week.
Find the latest version of the user-owned DIDxWallet smart contract here.
expo start
Demo file here.
(* The xWallet fields *)
(*--------------------*)
(* SSI Token implementations
@key: address
@value: token name *)
field xWallet: Map ByStr20 String = Emp ByStr20 String
(* SSI Token balances
@key: token name
@value: balance *)
field xBalances: Map String Uint128 = Emp String Uint128
(* SSI Token proxies
@key: token name
@value: address *)
field xProxies: Map String ByStr20 = Emp String ByStr20
(* The Donation Scheme
@key: campaign name
@value: campaign's starting block number *)
field donation: Map String BNum = Emp String BNum
procedure XWallet(
direction: XDirection,
amount: Uint128
)
this_token <- xWallet[_sender];
match this_token with
| Some token =>
this_balance <- xBalances[token];
balance = deconstruct_option_uint128 this_balance;
match direction with
| In =>
new_balance = builtin add balance amount;
xBalances[token] := new_balance
| Out =>
new_balance = builtin sub balance amount;
xBalances[token] := new_balance
end
| None =>
err = CodeNotSsiToken;
ThrowError err
end
end
(* Updates an SSI Token to its latest implementation *)
transition SsiToken(
token: String
)
IsRightStatus operational;
IsRightCaller user;
this_token_key <- verification_methods[token];
match this_token_key with
| Some token_key =>
this_tyron <- init_tyron;
msg = {
_tag: "SsiToken";
_recipient: this_tyron;
_amount: zero;
token: token
};
update_token = one_msg msg;
send update_token
| None =>
err = CodeNotSsiToken;
ThrowError err
end
end
(* The init.tyron contract calls this transition to update an SSI Token to its latest implementation *)
transition SsiTokenCallBack(
token: String,
proxyAddr: ByStr20,
tokenAddr: ByStr20
)
IsRightCaller tyron;
xWallet[tokenAddr] := token;
xProxies[token] := proxyAddr;
e = {
_eventname: "Updated_SSI_Token ";
ssi_token: token;
proxy_addr: proxyAddr;
token_addr: tokenAddr
};
event e
end
(* Initializes the donation campaign in the user's DID contract *)
transition Donate(
campaign: String
)
IsRightStatus operational;
this_tyron <- init_tyron;
msg = {
_tag: "Donate";
_recipient: this_tyron;
_amount: zero;
campaign: campaign
};
msg_donate = one_msg msg;
send msg_donate
end
transition DonateCallBack(
campaign: String
)
IsRightCaller tyron;
operation_cost[campaign] := zero;
current_block <- & BLOCKNUMBER;
donation[campaign] := current_block;
did <- decentralized_identifier;
e = {
_eventname: "Donation_campaign";
decentralized_identifier: did;
campaign: campaign
};
event e;
Timestamp
end
(* Transfers ZRC-2 SSI Tokens *)
transition XTransfer(
domain: String,
token: String,
agent: String,
to: ByStr20,
amount: Uint128,
signature: ByStr64
)
IsRightStatus operational;
IsRightCaller user;
Payment domain agent;
this_balance <- xBalances[token];
balance = deconstruct_option_uint128 this_balance;
is_enough = builtin lt amount balance;
match is_enough with
| True =>
this_token_key <- verification_methods[token];
signed_data = builtin to_bystr to;
IsRightSignature signed_data signature this_token_key;
this_proxy <- xProxies[token];
match this_proxy with
| Some proxy =>
msg = {
_tag: "Transfer";
_recipient: proxy;
_amount: zero;
to: to;
amount: amount
};
transfer = one_msg msg;
send transfer
| None =>
err = CodeNotProxy;
ThrowError err
end
| False =>
err = CodeWrongAmount;
ThrowError err
end
end
(* Adds native funds (ZIL) to the xWallet *)
transition ZilIn()
IsRightStatus operational;
accept;
did <- decentralized_identifier;
e = {
_eventname: "ZIL_received";
decentralized_identifier: did;
from: _sender;
amount: _amount
};
event e
end
(* Sends ZIL from the xWallet to any recipient that implements the tag (e.g. "ZilIn", "") *)
transition ZilOut(
tag: String,
to: ByStr20,
amount: Uint128
)
IsRightStatus operational;
IsRightCaller user;
accept;
msg = {
_tag: tag;
_recipient: to;
_amount: amount
};
transfer = one_msg msg;
send transfer;
did <- decentralized_identifier;
e = {
_eventname: "ZIL_sent";
decentralized_identifier: did;
tag: tag;
to: to;
amount: amount
};
event e;
Timestamp
end
(* Acceptance transition - must be defined or transfers to this xWallet will fail otherwise *)
transition RecipientAcceptTransfer(
sender : ByStr20,
recipient : ByStr20,
amount : Uint128
)
IsRightStatus operational;
XWallet incoming amount;
did <- decentralized_identifier;
e = {
_eventname: "Transfer_received";
decentralized_identifier: did;
sender: sender;
amount: amount
};
event e
end
(* Callback transition - must be defined or transfers from this xWallet will fail otherwise *)
transition TransferSuccessCallBack(
sender: ByStr20,
recipient: ByStr20,
amount : Uint128
)
IsRightStatus operational;
XWallet outcoming amount;
did <- decentralized_identifier;
e = {
_eventname: "Transfer_sent";
decentralized_identifier: did;
from: sender;
to: recipient;
amount: amount
};
event e;
Timestamp
end
For the specific case when the xTransfer is a donation, the domain parameter MUST be the donation campaign code, so the payment procedure executes as follows:
procedure Donation(
campaign: String
)
this_starting_block <- donation[campaign];
current_block <- & BLOCKNUMBER;
match this_starting_block with
| Some starting_block =>
is_valid =
let limit = builtin badd starting_block period in
builtin blt current_block limit;
match is_valid with
| True =>
| False =>
err = CodeNotValid;
ThrowError err
end
| None =>
err = CodeNotValid;
ThrowError err
end
end
(* Executes the payment to the agent and foundation *)
procedure Payment(
domain: String,
agent: String
)
calling_agent = Agent agent;
IsRightCaller calling_agent;
this_cost <- operation_cost[domain];
match this_cost with
| Some cost =>
is_donation = builtin eq cost zero;
match is_donation with
| True => Donation domain
| False => (* in development *)
end
| None =>
err = CodeNotSsiToken;
ThrowError err
end
end
Try the tyronzil Node.js client & donate from the command-line interface:
tyronzil donate