NEAR Protocol Fungible Tokens logic NEP-21 - smartcontracts

I have questions about:
fungible Token example and NEP-21 itself.
It's a possible situation when escrow allowances > 0, but account balance = 0.
Is it legal flow and why?
It never checks account_id exists or not. Why? Is it secure?
Anyone can call: inc_allowance/dec_allowance?
And for let owner_id = env::predecessor_account_id(); will be created new account, new escrow allowance automatically (if not exist). Is that logic correct and why?
get_account always created a new account. It looks redundant.
For example:
fn get_account(&self, owner_id: &AccountId) -> Account {
assert!(env::is_valid_account_id(owner_id.as_bytes()), "Owner's account ID is invalid");
let account_hash = env::sha256(owner_id.as_bytes());
self.accounts.get(&account_hash).unwrap_or_else(|| Account::new(account_hash))
}
Will create "always" new account for new owner_id. And it's possible then that account will never be used. So is it really practical to silently "create" an account with get_account?
transfer_from is never check owner_id as the real owner of the account. Is there logic to protect transferring only by real owners?
Why fungible token doesn't have a name/title?
Do the NEAR Protocol have some standard or logic for Fungible Tokens exchange?

It's a possible situation when escrow allowances > 0, but account balance = 0. Is it legal flow and why?
AFAIU allowance is just a sanity upper bound that prevents abuse. Two accounts can have two allowance for the same account that together sum up to a number larger than account balance.
It never checks account_id exists or not. Why? Is it secure?
In a sharded blockchain it is impossible to check for account existence without an asynchronous cross-contract call, since that other account might live on a different shard. Additionally, by the time we get a reply from that other shard this account can be created/deleted.
Anyone can call: inc_allowance/dec_allowance?
It can be only called by the owner, see: https://github.com/near/near-sdk-rs/blob/master/examples/fungible-token/src/lib.rs#L106
And for let owner_id = env::predecessor_account_id(); will be created new account, new escrow allowance automatically (if not exist). Is that logic correct and why?
Yes. I am not sure, why this would be contradictory.
get_account always created a new account. It looks redundant.
It might be redundant, but it also might be optimized out by the compiler in situations like this one: https://github.com/near/near-sdk-rs/blob/master/examples/fungible-token/src/lib.rs#L213
transfer_from is never check owner_id as the real owner of the account. Is there logic to protect transferring only by real owners?
It is implied in this check: https://github.com/near/near-sdk-rs/blob/master/examples/fungible-token/src/lib.rs#L174-L180 If it is not the case of an escrow, then env::predecessor_account_id() should be equal to owner_id. So the receipt/transaction must have been sent from the account of the owner.
Why fungible token doesn't have a name/title?
We are working on adding metadata to our contracts, see our Q1 OKRs here: https://airtable.com/shrw0AD36eIbfEW02
Do the NEAR Protocol have some standard or logic for Fungible Tokens exchange?
We have partners working on implementing something similar, but I don't think we have a standard.

Related

Bitcoinj - create temporary walllet

I'm new in bitcoin.
I need to create something like a temporary bitcoin wallet for the currency exchange app. The wallet should be alive just one exchange transaction or 2 days(if the transaction wouldn't confirmed) and then should be removed.
But as I understand right from bitcoin docs - I cannot remove a wallet, because it is sort a "public key".
Any suggestions?
A 'wallet' doesn't actually really exist. All it is, is a collection of private keys (or just one private key that can be used to derive other keys from, like HD wallets do). These private keys allow you to spend the unspent output (UTXO), thus make a transaction.
These private keys are used to generate public keys, and from those the addresses are generated. You can't remove these addresses because they just exist. In fact, every address already exists, you just need the private key to access them.
Removing things from the blockchain wouldn't make sense anyway, the blockchain is literally a chain of blocks, each block being a container filled with transactions. If you would remove a transaction from a block, all the following blocks would become invalid because the hash of your block's merkle tree would no longer add up.
That being said, you may want to look into HD wallets. You could do something like this (see BIP44):
m / purpose' / coin_type' / account' / change / address_index
Here you can use an incrementing ID for account, so that each use has his own account. You can then create a new address for each incoming payment (change = 0 for inbound external transactions, change 1 = for change coming from your own wallet).
This means that each payment/whatever will have its own address. Because it's a HD wallet you can still access all the addresses with the master key if you like.

Rails postgresql. Collision of two operations

I've got this shop-like application (Rails 3.2 + Postgresql), where two of my resources/tables are Users, and Operations. It has the following characteristics:
Amongst other attributes, Users have a certain :credit at each moment in time.
Operations represent either:
A purchase of a product (whose price is deduced from the User's credit who purchased it).
A purchase of credit ( the amount of which is added to the User's credit).
Each Operation stores:
:precredit - The credit the User had before the Operation.
:postcredit - The final credit after the Operation.
:price - The amount of money involved, whether it's positive or negative.
There was a problem with two Operation since they happened exactly at the same second ( My guess is that there was an internet problem for a while and then both queries were executed at the same second, see below).
This is the sorted sequence of operations by created_at(credit operations add and product operation subtract from the credit):
Category:credit Precredit:2.9 Price:30.0 Postcredit:32.9 Created_at:16:34:02
Category:product Precredit:32.9 Price:30.0 Postcredit:2.9 Created_at:16:42:06
Category:credit Precredit:32.9 Price:5.0 Postcredit:37.9 Created_at:16:42:06
Category:product Precredit:37.9 Price:4.0 Postcredit:33.9 Created_at:16:45:24
As one can see, Operation#3 should have a precredit = 2.9, which is the postcredit of Operation#2. However, the result of Operation#2 is not taken into account when Operation#3 is executed.
Ideally I would have:
Category:credit Precredit:2.9 Price:30.0 Postcredit:32.9 Created_at:16:34:02
Category:product Precredit:32.9 Price:30.0 Postcredit:2.9 Created_at:16:42:06
Category:credit Precredit:2.9 Price:5.0 Postcredit:-2.1 Created_at:16:42:06
Note that Operation#3 would've raised an error due to enough_balance?-type validations resulting in false.
Questions
Any ideas regarding how this might have happened?
How can this type of collisions be avoided?
I'm not sure how you're creating the operations, but this kind of situation can happen in concurrent environments, consider the next example:
Process A: gets the User object to obtain the current credit (equal to precredit)
Process B: gets the User object to obtain the current credit (at this point both have the same value)
Process A: calculates the postcredit (precredit +/- value)
Process B: calculates the postcredit
Process B: saves the record
Process A: saves the record
Even if the record in process A and the record in process B are not saved in the exact same millisecond (which is more unlikely), they still save both records with the same precredit, and this depends on how did they calculate this value. This is a common problem in operating systems and its solved with a 'Lock' (Peterson's algorithm,Lock)
Now, Rails provides a mechanism for achieving this, I recommend you take a look at http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html, the object you'll want to lock will probably be the user.

Storing tokens/uris returned from Balanced.js

Currently I am storing the 'Id' value returned by Balanced.js as the card/bank account token.
Then I suffix that with the API URI (/v1/marketplaces/TEST-MP5..../cards/) to charge cards.
Do I need to store the entire uri returned by Balanced.js ? What are the chances that stored URI prefix (/v1/...) will be changed in the future ?
What is the difference between the two end points for bank accounts? (cards seem to have only one uri: always prefixed with /v1/marketplaces..)
but bank accounts - looks like you can access the via:
/v1/bank_accounts/BA.... or
/v1/marketplaces/TEST-.../bank_accounts/BA...
Even the documentation differs for both. Why can't they be done consistently ?
https://docs.balancedpayments.com/current/api.html?language=php#adding-a-card-to-a-customer
Cards are added with:
$customer->addCard("/v1/marketplaces/TEST-MP.../cards/CC...")
https://docs.balancedpayments.com/current/api.html?language=php#adding-a-bank-account-to-a-customer
Bank accounts are added with
$customer->addBankAccount("/v1/bank_accounts/BA..")
Inconsistent documentation is confusing.. Thanks
You should always store the entire URI, constructing your own URI
from the ID can lead to conflicts with future API revisions.
There's no difference between the bank accounts. You may retrieve bank accounts from those endpoints. They will both result in the same bank accounts. There's some slight usability difference in both of them, but they're the same resource.

Searching Authorize.net CIM Records

Has anyone come up with an elegant way to search data stored on Authorize.net's Customer Information Manager (CIM)?
Based on their XML Guide there doesn't appear to be any search capabilities at all. That's a huge short-coming.
As I understand it, the selling point for CIM is that the merchant doesn't need to store any customer information. They merely store a unique identifier for each and retrieve the data as needed. This may be great from a PCI Compliance perspective, but it's horrible from a flexibility standpoint.
A simple search like "Show me all orders from Texas" suddenly becomes very complicated.
How are the rest of you handling this problem?
The short answer is, you're correct: There is no API support for searching CIM records. And due to the way it is structured, there is no easy way to use CIM alone for searching all records.
To search them in the manner you describe:
Use getCustomerProfileIdsRequest to get all the customer profile IDs you have stored.
For each of the CustomerProfileIds returned by that request, use getCustomerProfileRequest to get the specific record for that client.
Examine each record at that time, looking for the criterion you want, storing the pertinent records in some other structure; a class, a multi-dimensional array, an ADO DataTable, whatever.
Yes, that's onerous. But it is literally the only way to proceed.
The previously mentioned reporting API applies only to transactions, not the Customer Information Manager.
Note that you can collect the kind of data you want at the time of recording a transaction, and as long as you don't make it personally identifiable, you can store it locally.
For example, you could run a request for all your CIM customer profile records, and store the state each customer is from in a local database.
If all you store is the state, then you can work with those records, because nothing ties the state to a specific customer record. Going forward, you could write logic to update the local state record store at the same time customer profile records are created / updated, too.
I realize this probably isn't what you wanted to hear, but them's the breaks.
This is likely to be VERY slow and inefficient. But here is one method. Request an array of all the customer Id's, and then check each one for the field you want... in my case I wanted a search-by-email function in PHP:
$cimData = new AuthorizeNetCIM;
$profileIds = $cimData->getCustomerProfileIds();
$profileIds = $cimData->getCustomerProfileIds();
$array = $profileIds->xpath('ids');
$authnet_cid = null;
/*
this seems ridiculously inefficient...
gotta be a better way to lookup a customer based on email
*/
foreach ( $array[0]->numericString as $ids ) { // put all the id's into an array
$response = $cimData->getCustomerProfile($ids); //search an individual id for a match
//put the kettle on
if ($response->xml->profile->email == $email) {
$authnet_cid = $ids;
$oldCustomerProfile = $response->xml->profile;
}
}
// now that the tea is ready, cream, sugar, biscuits, you might have your search result!
CIM's primary purpose is to take PCI compliance issues out of your hands by allowing you to store customer data, including credit cards, on their server and then access them using only a unique ID. If you want to do reporting you will need to keep track of that kind of information yourself. Since there's no PCI compliance issues with storing customer addresses, etc, it's realistic to do this yourself. Basically, this is the kind of stuff that needs to get flushed out during the design phase of the project.
They do have a new reporting API which may offer you this functionality. If it does not it's very possible it will be offered in the near future as Authnet is currently actively rolling out lots of new features to their APIs.

Experimental/private branch for OID numbers in LDAP Schemas?

Attributes or object classes in LDAP schemas are identified through a unique number called OID. Moreover OIDs are also used in the SNMP protocol. Everyone can apply for an enterprise number by the IANA and then define his own subnumbers. But the processing of the application can last up to 30 days.
Does anyone know if there is a "test" branch of OID numbers that could be used for experimental purposes while waiting for an official enterprise number?
Apparently the OID branch 2.25 can be used with UUIDs without registration.
The detailled explanation can be found here:
http://www.oid-info.com/get/2.25 and there is also a link to an UUID generator.
=> I think it's good solution for unregistered OIDs. Simply generate one such OID with the UUID-Generator. You will get something like 2.25.178307330326388478625988293987992454427 and can then simply make your own subnumbers by adding .1, .2, ... at the end.
There is also the possibility to register such an 2.25 OID, but a human intervention is still needed and uniqueness isn't totally garanteed as it is still possible (although unlikely) that someone else uses the same OID as unregistered OID. For registered OIDs I would still prefer the registration of a private entreprise number by the IANA.
Here is also a list of how to get an OID assigned: http://www.oid-info.com/faq.htm#10. But the main answers are already listed here.
No. However, if there is nothing published from your work no one will know.
Some LDAP server companies will sub OID numbers if you wanted to try something. But you could just makeup anything.
The currently assigned numbers only start with 0, 1, or 2. If you started with 4 or something, any savey person would know you were faking it.
We put some info together on OIDs here:
http://ldapwiki.willeke.com/wiki/HowToGetYourOwnLDAPOID
-jim
I don't know where you're based. In the UK, each company gets it's own OID branch to play with as it will http://www.oid-info.com/get/1.2.826.0
(Not sure if there are similar setups in other countries
You could try following for internal prototyping (check "Object Identifiers (OIDs)" paragraph).