diff --git a/Dockerfile b/Dockerfile index 1a7edb62e..aeb48541a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,7 +63,7 @@ RUN mkdir -p /counterblock_data/asset_img /counterblock_data/asset_img.testnet # Install newest stable nodejs # (the `nodejs` package includes `npm`) RUN apt-get update && apt-get -y remove nodejs npm gyp -RUN curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - +RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - RUN apt-get update && apt-get -y install nodejs # Add transifex auth data if available @@ -74,8 +74,9 @@ ENV TRANSIFEX_PASSWORD ${TRANSIFEX_PASSWORD} RUN if [ -n "$TRANSIFEX_USER" ] && [ -n "$TRANSIFEX_PASSWORD" ]; then echo "$TRANSIFEX_USER:$TRANSIFEX_PASSWORD" > /root/.transifex; fi # Global stuff moved here to speed up build times just for code changes +RUN npm update -g npm RUN npm config set strict-ssl false -ENV PHANTOMJS_CDNURL="http://cnpmjs.org/downloads" +ENV PHANTOMJS_CDNURL="https://bitbucket.org/ariya/phantomjs/downloads" RUN npm install -g bower grunt browserify uglify-es RUN npm install --unsafe-perm -g mocha-phantomjs diff --git a/README.md b/README.md index 4f4b324f7..530311163 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Online Webwallet for [Counterparty](http://www.counterparty.io). Originally based off of [Carbonwallet](http://www.carbonwallet.com) (however virtually all the original code has been removed or rewritten). +[Counterwallet User Documentation](./docs/index.md) + Production Systems ------------------- diff --git a/docs/counterwallet-notes.md b/docs/counterwallet-notes.md new file mode 100644 index 000000000..19dbc5256 --- /dev/null +++ b/docs/counterwallet-notes.md @@ -0,0 +1,57 @@ +--- +title: Counterwallet notes +--- + +## More on multiple Counterwallet servers + +For the time being, the Counterparty team itself operates the primary Counterwallet platform at `counterwallet.io`. However, as Counterwallet is open source software, it is possible to host your own site with Counterwallet site (for your personal use, or as an offering to others), or to even host your own Counterwallet servers to use with your own Counterparty wallet implementation. The Counterparty team supports and encourages this kind of activity (as long as the servers are secure), as it aids with increasing decentralization. + +Also note that due to the nature of Counterwallet being a deterministic wallet, users using one Counterwallet platform (i.e. the official one, for instance) have the flexibility to start using a different Counterwallet platform instead at any time, and as funds (i.e. private keys) are not stored on the server in any fashion, they will be able to see their funds on either. (Note that the only thing that will not migrate are saved preferences, such as address aliases, the theme setting, etc.) + +## Counterwallet MultiAPI specifics + +Counterwallet utilizes a sort of a "poor man's load balancing/failover" implementation called multiAPI (and implemented +[here](https://github.com/CounterpartyXCP/counterwallet/blob/master/src/js/util.api.js)). multiAPI can operate in a number of fashions. + +### multiAPIFailover for Read API (``get_``) Operations + +*multiAPIFailover* functionality is currently used for all read API operations. In this model, the first Federated Node +on the shuffled list is called for the data, and if it returns an error or the request times out, the second one on the +list is called, and so on. The result of the first server to successfully return are used. + +Here, a "hacked" server could be modified to return bogus data. As (until being discovered) the server would be in the +shuffled list, some clients may end up consulting it. However, as this functionality is essentially for data queries only, +the worse case result is that a Counterwallet client is shown incorrect/modified data which leads to misinformed actions +on the user's behalf. Moreover, the option always exists to move all read-queries to use multiAPIConsensus in the future should the need arise. + +### multiAPIConsensus for Action/Write (``create_``) Operations + +Based on this multiAPI capability, the wallet itself consults more than one of these Federated Nodes via consensus especially +for all ``create_``-type operations. For example, if you send XCP, `counterparty-server` on each server is still composing and sending +back the unsigned raw transaction, but for data security, it compares the results returned from all servers, and will +only sign and broadcast (both client-side) if all the results match). This is known as *multiAPIConsensus*. + +The ultimate goal here is to have a federated net of semi-trusted backend servers not tied to any one country, provider, network or +operator/admin. Through requiring consensus on the unsigned transactions returned for all ``create_`` operations, 'semi-trust' +on a single server basis leads to an overall trustworthy network. Worst case, if backend server is hacked and owned +(and the `counterparty-server` code modified), then you may get some invalid read results, but it won't be rewriting your XCP send +destination address, for example. The attackers would have to hack the code on every single server in the same exact +way, undetected, to do that. + +Moreover, the Counterwallet web client contains basic transaction validation code that will check that any unsigned Bitcoin +transaction returned from a Counterblock Federated Node contains expected inputs and outputs. This provides further +protection against potential attacks. + +multiAPIConsensus actually helps discover any potential "hacked" servers as well, since a returned consensus set with +a divergent result will be rejected by the client, and thus trigger an examination of the root cause by the team. + +### multiAPINewest for Redundant storage + +In the same way, these multiple servers are used to provide redundant storage of client-side preferences, to ensure we +have no single point of failure. In the case of the stored preferences for instance, when retrieved on login, the data from all servers +is taken in, and the newest result is used. This *multiAPINewest* functionality effectively makes a query across all available +Federated Nodes, and chooses the newest result (based on a "last updated"-type timestamp). + +Note that with this, a "hacked" server could be modified to always return the latest timestamp, so that its results +were used. However, wallet preferences (and other data stored via this functionality) is non-sensitive, and thus user's +funds would not be at risk before the hacked server could be discovered and removed. diff --git a/docs/counterwallet-tutorials/broadcast.md b/docs/counterwallet-tutorials/broadcast.md new file mode 100644 index 000000000..1f7c28486 --- /dev/null +++ b/docs/counterwallet-tutorials/broadcast.md @@ -0,0 +1,23 @@ +--- +title: Broadcast information on the Bitcoin blockchain +--- + +Counterparty lets you publish text and data on the Bitcoin blockchain, this is called a 'broadcast'. This is useful for proof-of-publication, notary purposes, and creating betting feeds and oracles. This information is timestamped (as blocks), freely browseable and permanently stored on the Bitcoin blockchain. You can view and search broadcasts on a block explorer such as [XChain](https://xchain.io/broadcasts): + +![](../../../static/img/broadcast1.png) + +### How to publish a broadcast in Counterwallet + +**Click address actions and Feed Broadcast.** + +![](../../../static/img/broadcast2.png) + +**Enter the text or data you want to publish on the BTC blockchain. Note: The fields for fee and value are only used when creating a betting feed, you can leave the default values if you only wish to publish information.** + +**Note: The fields for fee and value are only used when creating a betting feed, you can leave the default values if you only wish to publish information. "Broadcast Date" (date picker) has no effect here (because timestamping is done by bitcoin miners) and may be removed in a future version.** + +![](../../../static/img/broadcast3.png) + +**Wait for the Bitcoin network to confirm your broadcast, and it will be visible online.** + +![](../../../static/img/broadcast4.png) diff --git a/docs/counterwallet-tutorials/buy-sell.md b/docs/counterwallet-tutorials/buy-sell.md new file mode 100644 index 000000000..6cb28bc75 --- /dev/null +++ b/docs/counterwallet-tutorials/buy-sell.md @@ -0,0 +1,58 @@ +--- +title: Buy and sell assets (tokens) on the DEx using XCP +--- + +This tutorial takes you through the process of buying and consequently selling a Counterparty-issued asset (or token/coin) from Counterwallet. By "Counterparty-issued" we mean "issued on the Counterparty platform by its users" as the Counterparty Project does not issue assets (XCP is the only asset that was issued by the Project). + +First, let's summarize how things work: + +1. All Counterparty assets can be traded on the Counterparty Decentralized Exchange and most Counterwallet sellers denominate their asset in XCP.  It is possible, but rare, to sell your asset A for another asset B, although that may be interesting in some cases. Some main advantages of decentralized crypto-exchanges are obviously decentralization (no counterparty risk) and a lower cost of filled orders. + +2. Some popular Counterparty-listed assets are available on traditional (centralized) crypto-exchanges such as Poloniex and MasterXchange where they are usually available denominated in BTC. This article covers only the DEx, but just so that you know the same asset can be traded on the DEx (usually denominated in XCP) and externally (usually denominated in BTC). Some advantages of centralized crypto-exchanges include the speed of trading and usually a better liquidity.  + +3. In order to buy an XCP-denominated asset, the user needs to complete the following steps: + +a) Create a wallet if you already don't have one (this one is easy, but make absolutely sure to write down your pass phrase). In case you'd like to practice first, there is a testnet (a network with "fake" (test) assets) wallet ([link](https://testnet.counterwallet.co/)) where you can open two wallets and practice without any risk or cost - see [What do I need to start using Counterwallet](https://counterpartytalk.org/t/what-do-i-need-to-start-using-counterwallet/1156). It is simpler, more reliable, faster and more secure to use Counterwallet in the private browsing mode (in Chrome, CTRL+SHIFT+N, in Firefox, CTRL+SHIFT+P) which disables extensions/addons (see [this for additional security-related](https://counterpartytalk.org/t/what-precautions-and-best-practices-can-i-use-for-counterwallet/1165) ideas). + +b) Buy some XCP on a and send XCP [and a small amount of BTC](https://counterpartytalk.org/t/why-do-i-need-small-amounts-of-bitcoin-to-do-things/1142) (e.g. 0.01) to your wallet address. + +c) Understand the fees (see [What is the difference between Total and Real Estimated Total when placing an order?](https://counterpartytalk.org/t/what-is-the-difference-between-total-and-real-estimated-total-when-placing-an-order/1178) and [What is the difference between 'miner's fee' and 'redeemable fee'?](https://counterpartytalk.org/t/what-is-the-difference-between-miners-fee-and-redeemable-fee/1188)), and [how to recognize fake (fraudulent) assets](https://counterpartytalk.org/t/how-to-recognize-fraudulent-counterparty-assets/1170)) + +d) Place a buy order on the DEx. If your offer gets matched within the duration of your order, your it will be settled. Otherwise it'll fail.  In case you change your mind or prices change, you can **cancel **your order before it expires (see [When is an order considered "active" and how can I cancel it?](https://counterpartytalk.org/t/when-is-a-dex-order-considered-active-and-how-can-i-cancel-it/1180)) + +Now that we covered the basics, let's walk through buy and sell scenarios. + +Before we move on let's remind ourselves that the default order validity (which can be changed in Counterwallet **Settings** and which does not persist between logons) is 1000 blocks of the Bitcoin blockchain, so if you trade in unstable assets you may want to change that to a lower value or even switch to a centralized crypto-exchange where it normally doesn't cost anything to place (and cancel) an order. See KB articles under 3d (above) for additional details. + +### Buy + +In Counterwallet's left-hand menu find **Exchange > Markets**. If you're after a popular asset, you may already see it among **Top Pairs**. Make sure you get the correct asset name(s). + +If not, move to the right and under **Select Another Pair **start typing the asset (token) name you're interested in. As you type Counterwallet will list available assets to save you time. Default unit of denomination is **XCP**, but you can select **Other **to enter another and as we mentioned above it is entirely possible that someone is selling WOOD for WATER. In that case you'd need have some WATER to buy WOOD and then you'd enter WOOD under **Token 1** and WATER under **Token 2**.  On a DEx level top assets (and their recent price trends) can be seen under **More > Top Assets**. + +Here we keep it simple and look for TESTASSETONE/XCP. + +![](../../../static/img/counterparty-dex-find-asset-to-buy1.jpg) + + +Once you click on TESTASSETONE, you will see the market. If it's any liquid, you'll see some buy and sell orders. We're buying so we're looking for Sell orders. At the very bottom of the screen we can see one sell offer: somebody is selling 22 TESTASSETONE in exchange for 2.2 XCP.   + +![](../../../static/img/counterparty-dex-select-sell-offer.jpg) + +If you're happy with that price, simply click on it and Counterwallet will populate your Buy Order form. Make sure the price is acceptable because matched orders cannot be cancelled! (It is not rare to hear that someone paid 0.001 for an asset that normally costs 0.0001.) + +A populated buy form can be modified (**Price, Amount**). Visually inspect all fields (especially if **Total** is a large number) to make sure one last time and then press the Buy button. + +![](../../../static/img/counterparty-dex-populate-buy-order.jpg) + +Now your order will remain valid until it's matched, cancelled or expired (whichever comes faster - see related KB mentioned under 3d, above).  + +Orders can be cancelled in two places - in **Exchange > Open Orders **and on the trading page for each asset pair where you have placed orders. The first location gives you a quicker way to see all your pending orders and cancel several on the same page. Orders can be partially matched and filled. + +You can monitor your order status using [https://xchain.io/](https://xchain.io/). + +### Sell + +Selling is executed the same way as buying, just in the opposite direction, so please refer to Buy section for details. + +The key part here is to carefully enter the price and quantity. Just because someone is offering 0.001 for your token that's normally selling for 0.01 doesn't mean you should click on their offer to auto-populate Sell order form with their values. If you are selling an asset that's also listed elsewhere (say, SJCX) you may want to check the price on other exchanges and see recently traded prices under **More > Top Assets**. diff --git a/docs/counterwallet-tutorials/change-token-settings.md b/docs/counterwallet-tutorials/change-token-settings.md new file mode 100644 index 000000000..6e6f1e1ed --- /dev/null +++ b/docs/counterwallet-tutorials/change-token-settings.md @@ -0,0 +1,34 @@ +--- +title: Change Token Settings +--- + +Once you have created a token, the address you have used will automatically be the owner of this token. This means that you will have access to certain token settings that can be changed. You can access these settings in Counterwallet by pressing the down arrow on the token's box. + +![](../../../static/img/change_token_settings1.png) + +**With ownership of a token you can:** +* change the token description +* issue additional units of your token +* lock the token in order to permanently prevent more unit from being issued +* transfer ownership of the token + +### Issue additional tokens +If your token is not locked, you will be able to issue additional units of your token to increase supply. Click "Issue Additional" to do so. This action is irreversible, but tokens can be sent to an unspendable address to effectively 'destroy' them if needed. + +![](../../../static/img/change_token_settings2.png) + +### Lock your token +If you would like to create a verifiably finite token, you will have to lock your token to prevent more units from being issued. Click "Lock Token Issuance" to do so. This action is irreversible. + +![](../../../static/img/change_token_settings3.png) + +### Change description +You can change the description of your token as often as you like. This will be publicly viewble in the blockchain. If you would like to add images, and additional information in your description, click [here](../../basics/assets/enhanced-asset.md) + +![](../../../static/img/change_token_settings4.png) + + +### Transfer ownership +You can transfer ownership, and therefore control over issuance and description, of your token. Please keep in mind this action takes some time, and is irreversible. + +![](../../../static/img/change_token_settings5.png) diff --git a/docs/counterwallet-tutorials/create-addresses.md b/docs/counterwallet-tutorials/create-addresses.md new file mode 100644 index 000000000..94129b767 --- /dev/null +++ b/docs/counterwallet-tutorials/create-addresses.md @@ -0,0 +1,51 @@ +--- +title: Creating a new address +--- + + +Counterwallet uses regular Bitcoin addresses, and you can create up to 20 in each wallet. If you need more, it is recommended and more secure if you create a new passphrase. + +**Counterwallet supports the creation of several different kinds of addresses:** + +- Regular Address +- [Armory Offline Address](create-armory-addresses.md) - compatible with the [Armory Wallet](https://bitcoinarmory.com/) +- Watch Only Address +- Multi-signature address + +### Creating a regular address + +It is very simple to create addresses, just click "Create New Address". + +![](../../../static/img/create_addresses1.png) + +You can create descriptions for your addresses. However, keep in mind that this information is not stored on the blockchain. Only you will be able to see the descriptions on your addresses. + +![](../../../static/img/create_addresses2.png) + +### Creating a watch-only address + +If you would like to monitor the BTC, XCP and asset balance of any address, you can create a watch-only address. This means that you will be able to see the balance, and create raw transactions. However, there is no private key associated with such addresses. This means that you will have to sign any transactions manually. This feature is useful for keeping track of your cold-storage coins. + +![](../../../static/img/create_addresses3.png) + +### Displaying the private key of your address + +If you would like to show the private key of an address, click address actions and show private key. If you cannot access Counterwallet for whatever reason, you can also generate your addresses and keys from your passphrase. For example, by using [this tool](https://blockscan.com/tool_generatekey). It's entirely client-side javascript. The source code is publicly visible, and you can even run it offline. + +![](../../../static/img/create_addresses4.png) + +Then you will be asked to confirm, to make sure nobody can see your screen. + +![](../../../static/img/create_addresses5.png) + + +### Customizing the appearance of your addresses + +Click the square next to address actions in order to set a color for your address. + +![](../../../static/img/create_addresses6.png) + +Click the - or + respectively next to the square in order to minimize or maximize the display of your address, for more space on your screen. + +![](../../../static/img/create_addresses7.png) + diff --git a/docs/counterwallet-tutorials/create-armory-addresses.md b/docs/counterwallet-tutorials/create-armory-addresses.md new file mode 100644 index 000000000..44564d7af --- /dev/null +++ b/docs/counterwallet-tutorials/create-armory-addresses.md @@ -0,0 +1,70 @@ +--- +title: Creating an Armory Offline Wallet for Cold Storage +--- + + +### + +**NOTE: This feature requires Armory 0.92.1 or later. As of this documentation update Counterwallet supports Armory 0.93.3.** + +Set up an Armory offline wallet using the instructions from [here](https://bitcoinarmory.com/tutorials/armory-basics/). Additional video instructions are [here](https://www.youtube.com/watch?v=PGvrai3JxxI). + +Create a Counterwallet account if you haven't already. Once logged in, go to Create New Address | Create Armory Offline Address: + +![Create Armory Address](../../../static/img/create_armory_address1.png) + +Copy an address from the Armory offline wallet, and paste it into the dialog box that appears. Then, press the Create New Address button: + +![Create Armory Address](../../../static/img/create_armory_address2.png) + +NOTE: The address you use must have at least one transaction being sent from it to be able to be used with Counterwallet. (This is because we require the public key to make transactions, which is only exposed when/if the address sends a transaction.) + +Your address will then show up on your Counterwallet Balances page, with whatever assets happen to already be at the address: + +![Create Armory Address](../../../static/img/create_armory_address3.png) + +With offline Armory addresses, you can do anything that you can do with a regular Counterwallet address (except for selling BTC on the Counterparty decentralized exchange). + +For example, let's send some XCP that's already at our Armory address to the other address in our wallet, and see how that works. To do this, click on the Send option under the address's XCP balance, just like you would with another address, and enter the other address you wish to send to, then click Send: + +![Create Armory Address](../../../static/img/create_armory_address4.png) + +![Create Armory Address](../../../static/img/create_armory_address5.png) + +Instead of seeing the transaction processed, you'll see a dialog that provides you with the unsigned transaction text: + +![Create Armory Address](../../../static/img/create_armory_address6.png) + +As the dialog states, you'll need to copy this text down to a text file on a USB key, and take that to the offline computer running Armory. + +On that offline computer, sign the transaction by going to Offline Transactions: + +![Create Armory Address](../../../static/img/create_armory_address7.png) + +Then, load the transaction text file from the USB key, which the interface will say is unsigned: + +![Create Armory Address](../../../static/img/create_armory_address8.png) + +Click on the Sign button, and enter your Armory wallet password, and the signed transaction will then be saved back to that same file: + +![Create Armory Address](../../../static/img/create_armory_address9.png) + +![Create Armory Address](../../../static/img/create_armory_address10.png) + +Safely eject the USB key, then insert it into your computer running Counterwallet and open up the file containing the transaction you just signed in a text editor: + +![Create Armory Address](../../../static/img/create_armory_address11.png) + +Copy down the text of the file to your clipboard. Then, back in Counterwallet, go to Address Actions | Broadcast Transaction for the armory address: + +![Create Armory Address](../../../static/img/create_armory_address12.png) + +On the dialog that appears, paste in the signed transaction, and then click Broadcast: + +![Create Armory Address](../../../static/img/create_armory_address13.png) + +If everything was done properly, you'll then see a dialog show that the broadcast was successful. The transaction should then be included in the blockchain by the next block, and the balance will then update (or whatever action you did will then take effect): + +![Create Armory Address](../../../static/img/create_armory_address14.png) + +**Congratulations**, you successfully made your first offline transaction with Counterwallet! Enjoy the peace of mind gained from your valuable assets being in cold storage with this feature. diff --git a/docs/counterwallet-tutorials/create-token.md b/docs/counterwallet-tutorials/create-token.md new file mode 100644 index 000000000..bf2637316 --- /dev/null +++ b/docs/counterwallet-tutorials/create-token.md @@ -0,0 +1,36 @@ +--- +title: Create a Token/NFTs +--- + + +Counterwallet makes it possible for anyone to create tokens (also known as assets, coins, derivatives) that are then owned by the address they were issued from. Ownership enables you to issue more units of your token, lock the supply, change the description, and customize other settings. To learn more about token settings, click [here](change-token-settings.md). + +Once the issuance is confirmed by the Bitcoin network, your tokens can be freely traded on the Counterwallet decentralized exchange against XCP and other tokens and (if you can convince them) centralized exchanges as well. + +Tokens can be divisible or indivisible. Tokens that are not divisible will only exist in whole units (1,2,3,etc.) Divisible tokens support up to 8 decimal places. You can create as many tokens as you need. + +### There are two types of tokens: + +**Alphabetical** + +Alphabetical tokens (for example BACON) can be named, but must be between 4 and 12 uppercase letters and cannot start with A. To create an alphabetical token, you will need enough BTC for a transaction fee and 0.5 XCP on the address you are using. This is an anti-spam fee, which aims to reduce the amount of names a single individual can register without significant costs. The anti-spam fee is burned (destroyed). + +**Numeric** + +Numeric (or more precisely alphanumeric) tokens (for example A12149713090358620000) are free to register and only require a Bitcoin transaction fee (like all other Counterwallet actions) on the issuing address. If you only want to create and trade numeric tokens, you will not require any XCP. Numeric tokens must start with an "A". + +### Creating a token is fairly simple: + +* Log in to or create a wallet in Counterwallet +* Make sure your addresss has enough BTC for a transaction fee (currently 0.0002 BTC) +* If you want to create an alphabetical token, your address will also need 0.5 XCP for the anti-spam fee +* Click *"Address Actions"* on your address +* Click *"Create a Token/Asset"* + +![](../../../static/img/create_token1.png) + +* Choose a type, description, quantity and divisiblity for your token. You can create a description for your token, which can either be plain text, a URL to your token’s official page, or a URL to a JSON file containing extended info. To learn more about extended info, look for information for Counterparty Enhanced Asset Info. It is also possible to register a token with an issuance of 0 units, as a placeholder. + +![](../../../static/img/create_token2.png) + + diff --git a/docs/counterwallet-tutorials/dex-trade.md b/docs/counterwallet-tutorials/dex-trade.md new file mode 100644 index 000000000..29adbc60f --- /dev/null +++ b/docs/counterwallet-tutorials/dex-trade.md @@ -0,0 +1,81 @@ +--- +title: Decentralized Exchange +--- + +It is possible to trade on the Counterparty decentralized exchange directly inside Counterwallet. You can trade any token against any other token, including XCP. (Trading against BTC is planned for the near future.) + +**Important:** But before you begin, please be aware this exchange inside Counterwallet is actually an interface to the Bitcoin network. This means that all tokens, buy, and sell orders are _all_ actually individual Bitcoin transactions. These transactions are then order matched by the protocol. This means that: + +* **All buy and sell orders are automatically escrowed _in the Bitcoin blockchain_ itself until they are completed.** The Counterparty exchange is decentralized and peer-to-peer. This means that there is never a third party or middleman (such as a server administrator, traditional exchange, clearing house, or bank). This kind of trading is called 'trustless', because you do not have to trust anyone to handle your funds and complete your trade correctly. + +![](../../../static/img/trade1.png) + +* Placing and cancelling orders requires the Bitcoin network to confirm these transactions, which may take some time. + +* Each action requires a basic transaction fee (like any other regular Bitcoin transaction.) + +* Some Counterwallet features may be restricted due to regulatory uncertainty in certain countries. This does not mean that they are disabled in the decentralized exchange. These features are simply hidden from the user interface by default to avoid legal issues. Like Bitcoin, Counterparty exists without international borders. So it is absolutely possible to use _any_ of the features in _any_ country by running your own copy of Counterwallet or Counterparty-cli, but please make 100% sure you are operating within the law before attempting this. + +**Disclaimer:** +All Counterwallet (and therefore Counterparty) actions are Bitcoin transactions. And because anyone can make a Bitcoin transaction, anyone can create a decentralized token. If this concept seems confusing, consider that Bitcoin functions entirely without a central bank. This is an identical 'free-for-all' scenario. It is _fundamentally_ impossible to have an 'owner' and or 'admins' at such an exchange. Escrowed funds are provably inaccessible until peer-to-peer orders are successfully matched, and all completed orders are irreversible. + +Counterparty (the open-source Bitcoin toolkit for financial instruments and markets) itself cannot distinguish whether tokens are legitimate, so please ensure due diligence before trading. Always research the official website of the token you are trading, its page on [XChain](https://xchain.io) and (if applicable) its thread on [Bitcointalk](http://bitcointalk.org). + +### Trading Basics + +Click **Exchange** `->` **Markets on the sidebar menu.** + +![](../../../static/img/trade2.png) + +You will see the pairs with the most current activity. Clicking on these will forward you to their orderbook. + +![](../../../static/img/trade3.png) + +You can also specify a custom token to trade, if it does not appear in the top pairs list. + +![](../../../static/img/trade4.png) + +Simply write your token in the field (autocomplete will try to help) and click XCP or other. Most tokens are primarily traded against XCP, but you can trade absolutely any token. If you want to trade a token you have just created, you need have to wait until it has been verified by the Bitcoin blockchain first.) + +![](../../../static/img/trade5.png) + +Then you will be able to see a graph showing the price and volume of that token (if there is enough data to display.) + +![](../../../static/img/trade6.png) + +Using this interface you can choose which of your addresses you are using to trade, and place orders directly. + +![](../../../static/img/trade7.png) + +Below this interface, you can look at the current orderbook for that pair. + +![](../../../static/img/trade8.png) + +And below that is a listing of previously completed trades, if there are any. + +![](../../../static/img/trade9.png) + +Let's try to buy 10 [LTBCOIN](http://ltbcoin.com/) just as an example. Set your desired price and amount, and press Buy. + +![](../../../static/img/trade10.png) + +Counterwallet will ask you to confirm your order to make sure everything is correct. + +![](../../../static/img/trade11.png) + +The order will now take some time to become valid and visible, while it is processed by the Bitcoin network. + +![](../../../static/img/trade12.png) + +You will be able to see the pending order by clicking the clock in the top left of the screen. + +![](../../../static/img/trade13.png) + +If you click the check to the left of the clock, you can see orders that have already been confirmed. + +![](../../../static/img/trade14.png) + +After a while, you will be able to see that the order confirmed. And if there is someone selling for the price that you are buying at, the order will be matched and completed automatically. + +![](../../../static/img/trade15.png) + diff --git a/docs/counterwallet-tutorials/get-token-info.md b/docs/counterwallet-tutorials/get-token-info.md new file mode 100644 index 000000000..b6bda0bda --- /dev/null +++ b/docs/counterwallet-tutorials/get-token-info.md @@ -0,0 +1,27 @@ +--- +title: Get Token Information +--- + +**Disclaimer:** All token information is provided by the creator and/or owner of the individual token and may not be accurate or up to date. Changing this information is an exclusive privilege of the address which owns the token on the blockchain. _All_ counterparty tokens are stored entirely in the Bitcoin blockchain and cannot be limited, restricted, or altered by anyone except their owner in any shape or form. + +### Showing information about a token you already have + +If you would like to learn more about a token you have, click on the down arrow in the token's box and then "Show Info". + +![](../../../static/img/get_token_info1.png) + +You will then be able to see basic information about the token such as the description, total issuance, whether it is locked or divisible, and a brief history of the token. + +![](../../../static/img/get_token_info2.png) + +### Showing information about any token + +If you want to see the information of any token at all even if you are logged out, then you can use a [block explorer](https://xchain.io) to search for the token. + +![](../../../static/img/get_token_info3.png) + +Here you will find a full overview of the token, as well as its holders, dividends, updates and dex orders. + +![](../../../static/img/get_token_info4.png) + +In order to find out whether a token is legitimate, it is a good idea to check the comments section in the block explorer, the token's official website, and social media such as [Bitcointalk](http://bitcointalk.org). diff --git a/docs/counterwallet-tutorials/getting-started.md b/docs/counterwallet-tutorials/getting-started.md new file mode 100644 index 000000000..3aab04088 --- /dev/null +++ b/docs/counterwallet-tutorials/getting-started.md @@ -0,0 +1,67 @@ +--- +title: Getting Started +--- + + +Counterwallet is an open-source web wallet for Bitcoin and Counterparty. It uses regular Bitcoin addresses, and lets you store Bitcoin, XCP, and user-created tokens without having to trust a server. What makes it different from many other web wallets, is that the _only_ possible way to access a wallet is by having access to the passphrase. In Counterwallet, none of your private information ever leaves your PC. + +For extra security, Counterwallet also supports watch-only addresses, offline transaction signing, and [Armory](https://bitcoinarmory.com/). + +### Creating a Wallet + +You can create as many wallets as you like. + +![](../../../static/img/getting_started_cw1.png) + +Your account in Counterwallet is secured by a 12 word passphrase. In fact, this passphrase _is_ your wallet itself. Every word in this phrase represents a number. Your browser places this passphrase into a math equation and gets a list of Bitcoin addresses and private keys as the result. If the passphrase is the same, you can always calculate the same addresses and keys. You can do this even if Counterwallet is offline. + +This means that your passphrase, your addresses and your private keys are never sent anywhere. This also makes it extremely important to keep your passphrase safe, as it cannot be restored by anyone. Please ensure that you have written it down correctly. Remember that once you close your browser, the only place this passphrase exists is the paper in your hand. + +![](../../../static/img/getting_started_cw2.png) + +After you have written down your passphrase, the next dialog will give you an option to create a custom quick access URL. This will make it possible to access your wallet with a password of your choosing, by encrypting your passphrase as a link. This feature is best used for wallets with a low amount of funds that need to be accessed very frequently. When logging in with a quick URL, you will only need to enter your password (and can avoid writing the 12 word passphrase every time). + +![](../../../static/img/getting_started_cw3.png) + +When you type a password, the URL will automatically adapt to be accessible for that password. Write the URL for your desired password down, and verify that it is correct by entering the same password again. + +![](../../../static/img/getting_started_cw4.png) + +You can log in to your wallet by writing your passphrase, and pressing open wallet. The open wallet button will only become active once you have entered a valid passphrase. + +![](../../../static/img/getting_started_cw5.png) + +If this is your first time logging in, you will have to agree to the terms and conditions of service. Some features may not be permitted in your country or jurisdiction. U.S. users cannot use dividend or betting functionality by default, for example. This is not a technical limitation, and can be disabled if you run your own Counterwallet, but bare in mind that legal difficulties may arise. We hope that U.S. regulation will become more clear on this matter. + +![](../../../static/img/getting_started_cw6.png) + +One important thing to know before getting started is that when you perform an action in Counterwallet (i.e. place an order, create a token, etc), it doesn't take effect immediately as it must first be confirmed on the Bitcoin blockchain. Counterwallet lets you know this by displaying your actions under the Pending Actions panel (the Clock icon on the top bar), and then moving them to the Notifications panel (the Checkbox icon) automatically once the network has successfully confirmed them. You'll also see the future expected value in parenthesis next to the current balance to better alert you that the change is pending. Note that depending on the speed at which blocks are solved, it could take anywhere from 2 to 40 minutes for your actions to be confirmed. + +### Sending and receiving BTC, XCP, and user-created tokens + +![](../../../static/img/getting_started_cw7.png) + +**One Bitcoin address will be automatically visible once you have created your wallet.** You can learn how to create more [here](create-addresses.md) and if you would like create an Armory address, you can read more about that [here](create-armory-addresses.md). + +![](../../../static/img/getting_started_cw8.png) + +You can send and receive both bitcoin and Counterparty tokens with it. To start using the wallet, simply send some BTC or XCP to the address (just single click on the address string itself to select it, then copy that text, which you can then give to others or use to send funds to). + +To send, click the down arrow button on BTC, XCP, or any user created token to show the drop-down menu. Then click send. + +![](../../../static/img/getting_started_cw9.png) + +Enter the address you wish to send to, and your desired amount. The "MAX" button will send the entire balance of your sending address, minus the fees necessary for the transfer. Press send to sign and broadcast the transaction. The transfer will be complete once it is verified by the Bitcoin network. + +![](../../../static/img/getting_started_cw10.png) + +### Logging in without a keyboard (to avoid malware) + +If you are worried about some form of malware reading your keyboard strokes, or cannot use a keyboard, it is possible to to use the on-screen keyboard to login. Simply click the blue keyboard icon to the right of the open wallet button. + +![](../../../static/img/getting_started_cw11.png) + +Then click on the text field of Word 1 to start typing. Note that this process is rather time consuming. Use it if you are worried or have reason to believe your computer has been compromised, and you need to move your coins. + +![](../../../static/img/getting_started_cw12.png) + diff --git a/docs/counterwallet-tutorials/multisig.md b/docs/counterwallet-tutorials/multisig.md new file mode 100644 index 000000000..8ababa10c --- /dev/null +++ b/docs/counterwallet-tutorials/multisig.md @@ -0,0 +1,31 @@ +--- +title: Using multisig with Counterwallet +--- + +Counterparty and Counterwallet support a basic form of multisig. Here’s an example of the process involved with creating and sending to and from a multisig address. Currently, 1-of-2, 2-of-2, 1-of-3, 2-of-3 and 3-of-3 multisig are supported at the moment. + +In this example, we’ll use a **2-of-3** multisig. With our multisig support, you may send and receive Bitcoin or any Counterparty asset (including XCP) in Counterwallet. + +## Creating a 2-of-3 multisig address: +* Create 3 separate Counterwallet accounts. (Each one will normally be owned by a separate person, although this is not a requirement.) +* Each new wallet will have 1 Bitcoin/Counterparty address by default. That will be utilized for the multisig +* Send some Bitcoin to each address in each of the 3 wallets +* For each address in each of the 3 wallets, send a very small amount (e.g. 0.0001) from them back to the sender address. This is necessary to broadcast each address' public key onto the blockchain, which Counterparty multisig currently requires to operate. +* In the first Counterwallet, click **Create New Address**, then choose **Create Multisig Address** +* On the dialog that appears, select 2-of-3 for **Type**, and enter the 3 addresses from the 3 separate Counterwallet accounts +* A multisig address entry will be created in that first Counterwallet account. Get that address by clicking on address area of the titlebar for it, and copying it. It will be in a format like: _2_1HrSbJR3fcjCDrp2mMJCzGrWR7jtYu4wq5_1Dzfoo4QmhMtHNthmC8hZBry3KPS9FUtgo_152f1muMCNa7goXYhYAQC61hxEgGacmncB_3_ +* Send a bit of BTC (e.g .001, .005, etc) to this multisig address from another address in your Counterwallet. This will be necessary for sending things _from_ the multi-sig address + +## To Receive BTC or a Counterparty asset to the multisig address: +* You can send to this address from another Counterwallet address just like you would with any other address, e.g. click **Send** for the appropriate asset in the appropriate sending address, paste in the full multisig address (as in above), and click **Send** again. + +## To Send BTC or a Counterparty asset from the multisig address: +* Log into the Counterwallet for the first multisig signer (which will have the entry for the multisig address) +* For the multisig address, click Address Actions, click **Send** for the appropriate asset, and fill out the required info. +* A raw unsigned TX will be produced once the Send dialog’s **Send** button is clicked +* On the 1st address that makes up that multisig (which, following this example, should be in that same Counterwallet account), click **Address Actions**, then click **Sign Transaction** +* Paste in the unsigned transaction and click **Sign** +* Copy the resultant text and send (email, etc) to the 2nd party +* The 2nd party will then do the same thing (sign the transaction in their Counterwallet account from their address that makes up 1 of the 3-of-3 multisig), except instead of clicking Sign, they will click **Sign and Broadcast**, as they will be the last signer. +* (**NOTE:** If you were doing this with a 3-of-3 multisig address, for instance, the 2nd party would instead just click **Sign** and then send to the 3rd party, who would do **Sign and Broadcast**. I.e. you will get as many signatures as you need, and the last party will sign and broadcast the transaction.) +* Upon clicking this, the fully signed multisig transaction is broadcast on the network and, once confirmed, the sent funds are disbursed. diff --git a/docs/counterwallet-tutorials/pay-distribution.md b/docs/counterwallet-tutorials/pay-distribution.md new file mode 100644 index 000000000..7069d425b --- /dev/null +++ b/docs/counterwallet-tutorials/pay-distribution.md @@ -0,0 +1,43 @@ +--- +title: How to Proportionally Distribute Funds to Token Holders +--- + +Counterparty natively supports payment distributions. This feature lets you distribute XCP, BTC or any other token to the holders of your own token. You can specify an amount per unit, and everyone who holds units of your own token will receive a proportional amount of the secondary token being distributed. Depending on the way it is used, this can also be referred to as 'dividend payments'. This feature has many clever uses, such as [transparent voting](voting.md). + +**For example:** + +1. You create a token TRADEME with 100 total units. +2. You sell 25 TRADEME to user A. +3. You sell 25 TRADEME to user B. +4. Now you have 50 TRADEME, while both users have 25 each. +5. Next, you make a distribution payment of 0.001 BTC per unit. +6. User A will receive 0.025 BTC +7. User B will receive 0.025 BTC + +### BTC Distributions +It is possible to pay out distributions using Bitcoin directly. However, this process is a regular Bitcoin transaction without any extra added data (which would make it a Counterparty transaction). This means it will not be possible to distinguish it as a Counterparty type transaction on block explorers or inside Counterwallet. It will simply appear as a regular BTC transaction with multiple recipients. + +Because this makes it difficult to distinguish distributions from regular transactions, we recommend that you use one address per asset, and do not use it for anything else. This will make it much easier to keep track of past BTC distributions. Otherwise it may be difficult for you and your users to get an overview of past distribution payments. + +### How to make a Distribution Payment in Counterwallet + +Choose the address which owns the token you want to make a distribution payment on. + +**Click address actions, and "Pay Distribution".** + +![](../../../static/img/distribution1.png) + +**Write the name of your token in the first field. You can only distribute funds to a token you have issued or control.** + +![](../../../static/img/distribution2.png) + +**Specify the token to be distributed.** + +![](../../../static/img/distribution3.png) + +**Specify the amount of the token to be distributed per unit ("_share_") and the costs will be displayed. Click "Pay Distribution" and after a while it will be confirmed by the Bitcoin network.** +![](../../../static/img/distribution4.png) + +**Once the distribution has been confirmed, you will be able to see it on a [block explorer](https://xchain.io). Note that you can only see XCP and asset distributions, while BTC distributions will be visible as BTC transactions.** + + diff --git a/docs/counterwallet-tutorials/show-qrcode.md b/docs/counterwallet-tutorials/show-qrcode.md new file mode 100644 index 000000000..f4e00ddae --- /dev/null +++ b/docs/counterwallet-tutorials/show-qrcode.md @@ -0,0 +1,19 @@ +--- +title: Show QR Code for Address +--- + +A Quick Response code, commonly known as a QR code, is an image containing scannable information. In the context of Bitcoin and Counterparty, QR codes usually represent Bitcoin addresses. (Although private keys can also be displayed as QR codes for paper wallets as well.) QR codes make it easier for users on mobile devices to send BTC, XCP, or user-created assets to your address by using the built-in camera of their device. + +It is also a great way to display a Bitcoin address on a poster or sign. Someone passing by will only need a camera or phone with a camera (even low resolution will do) in order to save your address for later payment. And if they have a Bitcoin wallet on their device, they will be able to send money immediately. + +In Counterwallet, the QR codes always represent your public address. You can make the QR code of an address public, just as you would with the regular address. + +**To display the QR code for your address, simply click address actions.** + +![](../../../static/img/show_qr_code1.png) + +**Then click Show QR Code.** + +![](../../../static/img/show_qr_code2.png) + +You can then right-click and save the QR code image for printing, or later use. It is also possible to scale the QR code to a larger size, as long as you preserve the ratio between width and height so that it stays a perfect square. Always leave a white border around the QR code so that it can be scanned correctly. Also make sure that you preserve the contrast of colors: black QR on a white background. diff --git a/docs/counterwallet-tutorials/voting.md b/docs/counterwallet-tutorials/voting.md new file mode 100644 index 000000000..57321924c --- /dev/null +++ b/docs/counterwallet-tutorials/voting.md @@ -0,0 +1,28 @@ +--- +title: Voting with Tokens +--- + +Counterparty supports voting through user-created tokens, as well as broadcasting information onto the Bitcoin blockchain. This means that you can post the terms and options of your vote as a broadcast, and let users vote on its outcome with full transparency by using tokens. + +If you create an token (‘EXAMPLE’), you can create any other tokens (such as EXAMPLEVOTE) and [pay distributions](pay-distribution.md) of EXAMPLEVOTE to all holders of EXAMPLE in one single action. + +To send available votes to the holders of your asset, go to Counterwallet and click on your asset EXAMPLE, and then click pay distribution. Choose EXAMPLEVOTE as the currency to distribute. This way, all holders of EXAMPLE will receive EXAMPLEVOTE in the amount you specify. + +Now all you need are as many different Bitcoin addresses as there are choices in your poll. To cast their votes, holders of EXAMPLE can then send the EXAMPLEVOTE they have received to whichever choice(s) they agree with. The results of the poll will be public and verifiable thanks to the Bitcoin blockchain. + +**Example:** +* 10 users own the token "EXAMPLE". +* You make a distribution payment of EXAMPLEVOTE. +* Now each of the 10 users receives EXAMPLEVOTE proportionally to their holdings of EXAMPLE. +* You create a address for each option of the vote. +* You create a broadcast from the issuance address, describing the vote, the choices, and the addresses which represent the choices. + +It may be a good idea to create burn addresses for this purpose (addresses where the private key is not known). This way, the votes cannot be recycled or moved. This can be done with a [simple python script](https://gist.github.com/CoinWhisperer/6d673f1f3d13da1611cd) + +### Monitoring votes + +If you want to get info about your votes, or other polls, you can use the voting page on the block explorer [Blockscan](http://blockscan.com/votes). + +**For [example](http://blockscan.com/vote/FLDCVOTEI):** + +![](../../../static/img/voting_with_tokens1.png) \ No newline at end of file diff --git a/docs/counterwallet.md b/docs/counterwallet.md new file mode 100644 index 000000000..1f26d6beb --- /dev/null +++ b/docs/counterwallet.md @@ -0,0 +1,114 @@ +--- +title: Counterwallet FAQ +--- + + +## What is Counterwallet? + +**Counterwallet is an open-source web wallet for Bitcoin (BTC) and [Counterparty](https://github.com/CounterpartyXCP/) (XCP), the world’s first protocol for decentralized financial tools. It is built using Javascript, Bitcoin libraries and Counterparty software.** + +* Counterwallet handles transaction signing locally, which means your passphrase and private keys never leave your browser. + +* Additional security features such as m-of-n (max 3) multi-signature addresses, watch-only, and [Armory](counterwallet-tutorials/create-armory-addresses.md) addresses are also natively supported. + +* All trades and actions made with Counterwallet use a secure automatic escrow system within the Bitcoin blockchain, which means that unlike centralized exchanges, _no middleman is ever required_. + +## What are some of Counterwallet's features? + +- Supports BTC, XCP and all Counterparty assets +- Create and manage new assets (tokens) on the Bitcoin blockchain +- Distribute profits to asset holders using BTC, XCP, or any other + Counterparty token (asset) +- Broadcast data feeds to the Bitcoin network +- Trade XCP for any Counterparty asset (peer-to-peer) +- Access P2P assets with no middleman, and no counterparty risk +- Monitor the Counterparty network statistics +- Strong privacy - no registration required; you can run your own + Counterwallet +- Multilingual (English, Chinese, Russian and other languages) - + [become a translator!](https://www.transifex.com/organization/counterparty/dashboard/counterwallet) +- Deterministic hierarchical wallet +- Supports desktop and mobile browsers +- Client-side authentication/encryption +- Cold storage support (with Armory) +- Multi-sig support (up to 3-of-3) +- Watch-only addresses + +## Where can I access it? + +Counterwallet (CW) hosted by the Counterparty project is available at [Counterwallet.io](https://counterwallet.io/). However, because Counterwallet source code is [open source](https://github.com/CounterpartyXCP/counterwallet/), anyone can host and alter their own instance of Counterwallet. Those instances, however, are not under control of Counterparty.io, so it is up to the user to assess reliability and trustworthiness of the host. + +## What is an Asset/Token/Coin? How can I store them? + +Assets (also known as tokens or coins) are user-created currencies that are stored inside the Bitcoin blockchain using Counterparty technology. Anyone can create their own. + +All Counterwallet addresses are regular Bitcoin addresses. You can store BTC, XCP, and user created assets on any Counterwallet address. In fact, you can store any of these currencies on any regular Bitcoin address as well, provided that you have access to the private key of that address. + +(Altcoins that have their own blockchain, which is seperate from the Bitcoin blockchain, are not supported.) + +## I want to trade a certain asset, is it legitimate? + +Assets/tokens are issued on the Bitcoin blockchain directly. This means that anyone with access to the internet is able to create and trade tokens freely without restrictions. There is no way to block Bitcoin addresses and transactions, which means that there is also no way to limit any Counterparty activity. We recommend significant due diligence and research before trading. Counterwallet does not filter any assets. Please check the official website of whatever asset/token you are planning to trade, and make sure to verify that it is legitimate. + +## Is Counterwallet down? + +Counterparty health status monitor is available [here](http://platform.counterparty.io/). Should the server you're connecting to be unresponsive or time out, you can try to directly access another of servers listed at [counterwallet.io](https://counterwallet.io/). It is also possible that Counterwallet is being updated or dealing with a blockchain reorganization. + +## Counterwallet is offline. Can I still access my funds? + +Yes, and your orders and assets are still there*. You can mathematically generate your public and private keys using your passphrase. Since the addresses are generated on the fly using JavaScript, it is possible to do this in your own browser (even offline). You can use [this tool](https://blockscan.com/tool_generatekey). + +* The Counterparty Distributed Exchange is actually part of the Bitcoin blockchain. This means that Bitcoin itself would have to be shut down entirely in order for it to go offline. + +## How does Counterwallet make profit? + +It doesn't! Counterwallet development is a public service to the Counterparty and Bitcoin community. If you would like to contribute, you can click the donate button within Counterwallet itself. Or you can fork [the code](https://github.com/CounterpartyXCP/counterwallet/) and contribute that way. + +## Can I try Counterwallet on testnet? + +Yes, you can test Counterwallet by using a testnet instance located at [testnet.counterwallet.io](https://testnet.counterwallet.io/). Once you log on, get some testnet Counterparty tokens from the faucet as explained on the welcome page. + +## Can I use Counterwallet with Armory? + +Sure. + +Add an address in an offline armory wallet, [here's how](https://bitcoinarmory.com/about/using-our-wallet/) +to your Counterwallet, and do something with the address (like send some XCP from that address), which will produce the armory unsigned transaction text. Copy it to a USB key, take it to your offline computer running Armory (which has the private keys), sign it on that computer via the Armory GUI, and then broadcast the signed transaction back in Counterwallet. + +This will make use of assets owned in this address very secure... Basically Armory will act as cold storage of Counterparty assets, with almost the usability of a hot wallet. + +## I logged in and my address is different, and I have no balance! Help! + +In rare circumstances an address can disappear from the view. You can add another address from the Counterwallet user interface and in all likelihood the address will reappear. Otherwise you can use [this tool](https://blockscan.com/tool_generatekey) to obtain the private key for the missing address and then use the import feature in Counterwallet to import its assets to another address in your Counterwallet. + +## I sent BTC to Counterwallet, why doesn't it show up? + +It either was not sent, or it has not arrived. To check for BTC transactions, use a Bitcoin blockchain explorer (e.g. blockchain.info) and to check for XCP and other Counterparty-based tokens, use xchain.io or coindaddy.io. + +## Why do I need small amounts of Bitcoin to do things in Counterwallet? + +Counterparty builds directly on top of the Bitcoin network, and every Counterparty transaction is a Bitcoin transaction as well. This means that Counterparty transactions are the same as as Bitcoin transactions, with some information attached. + +Because of this, Counterparty transactions must pay a small BTC fee to the Bitcoin miners for each transaction sent. Beyond being a sign of our commitment to the health of the Bitcoin network, this allows Counterparty transactions to be given a high priority and be confirmed quickly. + +If speed of confirmation is not as important to you as the fee amount paid, note that it is possible to have lower fees in Counterparty, especially involving bulk sends. This functionality will also be coming to Counterwallet as well. + +## Does Counterwallet support two-factor authentication? + +Currently, no. But you can create multi-signature addresses to better protect your assets. + +## What else do I need to know? + +- All encryption is handled client-side. Neither your passphrase nor any of your private information ever leaves your browser. This also means that there is no password recovery, so make sure you do not lose your passphrase. + +- Because Counterwallet does not store your credentials, it has no access to your information. However it is important to use a reputable Counterwallet provider. + +- Because of the US government regulations, betting functionality is limited to non-US-based client IP addresses by default. This is not a limitation of the protocol itself. Please ensure that the use-case you are aiming for is legal within your jurisdiction, and seek professional legal advice when starting a project. + +## Can I run my own Counterwallet server? + +Yes, although that requires a full bitcoin node and some technical knowledge. Please refer to [this page](../advanced/federated-node/getting-started.md) for details on how to setup a Counterparty Federated Node. If you are starting from scratch, it may take several days to download and index the bitcoin blockchain. + +## I want to translate Counterwallet to my language + +Translations are hosted at [Transifex](https://www.transifex.com/organization/counterparty/dashboard/counterwallet). Open an account (or login with Github) and contribute as a translator or reviewer. We appreciate any contributions. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..90b2f113a --- /dev/null +++ b/docs/index.md @@ -0,0 +1,18 @@ +# Counterwallet User Documentation + +1. [Counterwallet FAQ](./counterwallet.md) +1. Counterwallet Tutorials + 1. [Getting Started](./counterwallet-tutorials/getting-started.md) + 1. [Creating a new address](./counterwallet-tutorials/create-addresses.md) + 1. [Decentralized Exchange](./counterwallet-tutorials/dex-trade.md) + 1. [Using multisig with Counterwallet](./counterwallet-tutorials/multisig.md) + 1. [Show QR Code for Address](./counterwallet-tutorials/show-qrcode.md) + 1. [Get Token Information](./counterwallet-tutorials/get-token-info.md) + 1. [Create a Token/NFTs](./counterwallet-tutorials/create-token.md) + 1. [Change Token Settings](./counterwallet-tutorials/change-token-settings.md) + 1. [How to Proportionally Distribute Funds to Token Holders](./counterwallet-tutorials/pay-distribution.md) + 1. [Broadcast information on the Bitcoin blockchain](./counterwallet-tutorials/broadcast.md) + 1. [Voting with Tokens](./counterwallet-tutorials/voting.md) + 1. [Buy and sell assets (tokens) on the DEx using XCP](./counterwallet-tutorials/buy-sell.md) + 1. [Creating an Armory Offline Wallet for Cold Storage](./counterwallet-tutorials/create-armory-addresses.md) +1. [Counterwallet notes](./counterwallet-notes.md) diff --git a/src/.bowerhashes b/src/.bowerhashes index e745ef00e..9f715a717 100644 --- a/src/.bowerhashes +++ b/src/.bowerhashes @@ -53,7 +53,6 @@ "src/vendors/select2/select2.min.js": "231818c9b851ff39ad5f17dc24837c79560199e7fdaa3eb0be153527a2b9e0bd", "src/vendors/jqlog/jquery.jqlog-1.3.min.js": "15bdd1693ad39873922e017c5570c49233c5d5e7c2f209ec32145b3badf36291", "src/vendors/async/dist/async.js": "f5dd34a865030d09efd42f623611c63be542d8f1bb61dcb0857305d8e8b82ff7", - "src/vendors/iso8601-js-period/iso8601.min.js": "2b143cf4c690e01f1ae2c3e529d7ddf682aea712fae1272a21973d7319842fde", "src/vendors/queue/queue.min.js": "2e56829c7d093bf017ec637aee858e33378a993686144e296da984a8f6029355", "src/vendors/htmlcanvas/build/html2canvas.js": "d13063b4e7bdf2a4a37c0d4102aba1f010e369b1f421154e0a78b040bead01c3", "src/vendors/sprintf/dist/sprintf.min.js": "e12b992b6797e823c724558ffa0e42c3e3f831c6c6094b19c374b2dae3243e6c", diff --git a/src/bower.json b/src/bower.json index 95e3f4f68..785989d35 100644 --- a/src/bower.json +++ b/src/bower.json @@ -17,8 +17,8 @@ "jqBootstrapValidation": "1.3.7", "jqlog": "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jqlog/jqlog-1.3.zip", "keyboard": "1.18.8", - "jReject": "1.0.2", - "jReject-ie11": "https://raw.githubusercontent.com/TurnWheel/jReject/39e310ffb8659488f3d376b721b3a54c89a19d68/js/jquery.reject.js", + "jReject": "1.1.5", + "jReject-ie11": "https://raw.githubusercontent.com/TurnWheel/jReject/8cdb9d6c4f4881c6eff1848643b19cada3b0f81d/js/jquery.reject.js", "jquery.slimscroll": "1.3.1", "jquery-timeago": "1.4.0", "jquery-yql": "https://raw.githubusercontent.com/hail2u/jquery.query-yql/655264551b7962485bcf0d06226e053a6f24629b/jquery.query-yql.js", @@ -36,7 +36,6 @@ "bitcore-message": "1.0.2", "mocha": "1.18.2", "chai": "1.9.1", - "iso8601-js-period": "https://github.com/nezasa/iso8601-js-period.git#v0.2.0.0", "queue": "https://github.com/mbostock/queue.git#v1.0.7", "htmlcanvas": "git://github.com/niklasvh/html2canvas.git#33e96032800a71e2ea8d0cff556ec940412a8527", "sprintf": "git://github.com/alexei/sprintf.js.git#d5cfad02b3db7a472544b1d9e467fcc126e453a9", diff --git a/src/js/components/asset.js b/src/js/components/asset.js index eb94b610d..b3abb7cdc 100644 --- a/src/js/components/asset.js +++ b/src/js/components/asset.js @@ -48,6 +48,10 @@ function AssetViewModel(props) { return self.owner() == self.ADDRESS; }, self); + self.canBeReset = ko.computed(function() { + return self.isMine() && (self.rawSupply() == self.rawBalance()); + }, self); + self.normalizedBalance = ko.computed(function() { if (self.rawBalance() === null) return null; return normalizeQuantity(self.rawBalance(), self.DIVISIBLE); @@ -61,6 +65,10 @@ function AssetViewModel(props) { return smartFormat(self.normalizedTotalIssued()); }, self); + self.divisibleLabel = ko.computed(function() { + return (self.DIVISIBLE?i18n.t("is_divisible"):i18n.t("is_not_divisible")); + }, self); + self.assetType = ko.computed(function() { if(_.startsWith(self.ASSET, 'A') && !self.ASSET_LONGNAME) { return 'numeric'; @@ -184,6 +192,12 @@ function AssetViewModel(props) { }); }; + self.reset_asset = function() { + assert(self.canBeReset()); + if (!WALLET.canDoTransaction(self.ADDRESS)) return false; + RESET_ASSET_MODAL.show(self.ADDRESS, self.DIVISIBLE, self.SUPPLY, self); + }; + self.changeDescription = function() { if (!WALLET.canDoTransaction(self.ADDRESS)) return false; CHANGE_ASSET_DESCRIPTION_MODAL.show(self.ADDRESS, self); diff --git a/src/js/components/balances.js b/src/js/components/balances.js index dae0bd58c..7101def0a 100644 --- a/src/js/components/balances.js +++ b/src/js/components/balances.js @@ -887,7 +887,7 @@ function CreateDispenserModalViewModel() { self.mainchainrate = ko.observable().extend({ required: true, isValidPositiveQuantity: self, - isValidQtyForDivisibility: self, + //isValidQtyForDivisibility: true, validation: { validator: function(val, self) { return true; diff --git a/src/js/components/balances_assets.js b/src/js/components/balances_assets.js index f0cc049d0..71610d413 100644 --- a/src/js/components/balances_assets.js +++ b/src/js/components/balances_assets.js @@ -273,6 +273,112 @@ function CreateAssetModalViewModel() { } } +function ResetAssetModalViewModel() { + var self = this; + + self.shown = ko.observable(false); + self.address = ko.observable(''); + self.divisible = ko.observable(); + self.asset = ko.observable(); + + self.totalSupply = ko.observable(); + self.wasDivisible = ko.observable(); + + self.quantity = ko.observable().extend({ + required: true, + isValidPositiveQuantityOrZero: self, + isValidQtyForDivisibility: self + }); + + self.validationModel = ko.validatedObservable({ + quantity: self.quantity + }); + + self.resetForm = function() { + self.divisible(true); + self.quantity(null); + self.validationModel.errors.showAllMessages(false); + self.feeController.reset(); + } + + self.submitForm = function() { + if (!self.validationModel.isValid()) { + self.validationModel.errors.showAllMessages(); + return false; + } + + //data entry is valid...submit to the server + $('#resetAssetModal form').submit(); + } + + self.doAction = function() { + WALLET.doTransactionWithTxHex(self.address(), "create_issuance", self.buildResetAssetTransactionData(), self.feeController.getUnsignedTx(), + + function(txHash, data, endpoint, addressType, armoryUTx) { + self.shown(false); + + var message = i18n.t("you_have_reset", self.asset().ASSET, self.quantity(), (self.divisible()?i18n.t("divisible"):i18n.t("not_divisible"))); + + WALLET.showTransactionCompleteDialog(message + " " + i18n.t(ACTION_PENDING_NOTICE), message, armoryUTx); + } + + + ); + + self.shown(false); + trackEvent('Assets', 'ResetAsset'); + } + + self.buildResetAssetTransactionData = function() { + var quantity = parseFloat(self.quantity()); + var rawQuantity = denormalizeQuantity(quantity, self.divisible()); + + if (rawQuantity > MAX_INT) { + bootbox.alert(i18n.t("issuance_quantity_too_high")); + return false; + } + + return { + source: self.address(), + asset: self.asset().ASSET, + quantity: rawQuantity, + divisible: self.divisible(), + lock: false, + reset: true, + description: self.asset().description(), + transfer_destination: null, + _fee_option: 'custom', + _custom_fee: self.feeController.getCustomFee() + } + } + + self.feeController = CWFeeModelMixin(self, { + action: "create_issuance", + transactionParameters: [self.quantity, self.divisible], + validTransactionCheck: function() { + return self.validationModel.isValid(); + }, + buildTransactionData: self.buildResetAssetTransactionData + }); + + self.show = function(address, divisible, quantity, asset, resetForm) { + if (typeof(resetForm) === 'undefined') resetForm = true; + if (resetForm) self.resetForm(); + self.totalSupply(quantity); + self.wasDivisible(divisible?i18n.t("divisible"):i18n.t("not_divisible")); + + self.address(address); + self.divisible(divisible); + self.asset(asset); + self.quantity(quantity); + self.shown(true); + trackDialogShow('ResetAsset'); + } + + self.hide = function() { + self.shown(false); + } +} function IssueAdditionalAssetModalViewModel() { var self = this; diff --git a/src/js/components/feed_notifications.js b/src/js/components/feed_notifications.js index 49619be71..37ab0f7f9 100644 --- a/src/js/components/feed_notifications.js +++ b/src/js/components/feed_notifications.js @@ -85,6 +85,10 @@ NotificationViewModel.calcText = function(category, message) { desc = i18n.t("notif_token_locked", message['_asset_longname'] || message['asset']); } else if (message['description'] != assetObj.description()) { desc = i18n.t("notif_token_desc_changed", message['_asset_longname'] || message['asset'], assetObj.description(), message['description']); + } else if (message['reset']) { + var newQuantity = message['quantity']; + var newDivisibility = message['divisible']; + desc = i18n.t("notif_token_reset", message['_asset_longname'] || message['asset'], smartFormat(normalizeQuantity(newQuantity, assetObj.DIVISIBLE)), (assetObj.DIVISIBLE?i18n.t("divisible"):i18n.t("not_divisible"))); } else { var additionalQuantity = message['quantity']; if (additionalQuantity) { diff --git a/src/js/components/feed_pending_actions.js b/src/js/components/feed_pending_actions.js index 1e38a945b..e5d50f6f8 100644 --- a/src/js/components/feed_pending_actions.js +++ b/src/js/components/feed_pending_actions.js @@ -64,6 +64,8 @@ PendingActionViewModel.calcText = function(category, data) { desc = i18n.t("pend_or_unconf_issuance", pending, asset_longname || data['asset'], numberWithCommas(normalizeQuantity(data['quantity'], data['divisible']))); } + } else if (data['reset']) { + desc = i18n.t("pend_or_unconf_reset", pending, asset_longname || data['asset'], numberWithCommas(normalizeQuantity(data['quantity'], data['divisible'])), (data['divisible']?i18n.t('divisible'):i18n.t('not_divisible'))); } else { //See if this is a new issuance or not var assetObj = null; @@ -315,6 +317,13 @@ PendingActionFeedViewModel.modifyBalancePendingFlag = function(category, data, f updateUnconfirmedBalance(data['source'], data['asset'], data['quantity'] * -1); updateUnconfirmedBalance(data['destination'], data['asset'], data['quantity']); + } else if (category == 'issuances' && data['reset']) { + addressObj = WALLET.getAddressObj(data['source']); + var assetObj = addressObj.getAssetObj(data['asset']); + if (assetObj && assetObj.isMine()) { + assetObj.issuanceQtyChangePending(flagSetting); + assetObj.balanceChangePending(flagSetting); + } } else if (category == 'issuances' && !data['locked'] && !data['transfer_destination']) { //with this, we don't modify the balanceChangePending flag, but the issuanceQtyChangePending flag instead... addressObj = WALLET.getAddressObj(data['source']); diff --git a/src/js/pages.init.js b/src/js/pages.init.js index 6aefbc5e6..b31bbdd58 100644 --- a/src/js/pages.init.js +++ b/src/js/pages.init.js @@ -151,6 +151,7 @@ function initBalances() { //balances_assets.js window.CREATE_ASSET_MODAL = new CreateAssetModalViewModel(); window.ISSUE_ADDITIONAL_ASSET_MODAL = new IssueAdditionalAssetModalViewModel(); + window.RESET_ASSET_MODAL = new ResetAssetModalViewModel(); window.TRANSFER_ASSET_MODAL = new TransferAssetModalViewModel(); window.CHANGE_ASSET_DESCRIPTION_MODAL = new ChangeAssetDescriptionModalViewModel(); window.PAY_DIVIDEND_MODAL = new PayDividendModalViewModel(); @@ -158,6 +159,7 @@ function initBalances() { ko.applyBindings(CREATE_ASSET_MODAL, document.getElementById("createAssetModal")); ko.applyBindings(ISSUE_ADDITIONAL_ASSET_MODAL, document.getElementById("issueAdditionalAssetModal")); + ko.applyBindings(RESET_ASSET_MODAL, document.getElementById("resetAssetModal")); ko.applyBindings(TRANSFER_ASSET_MODAL, document.getElementById("transferAssetModal")); ko.applyBindings(CHANGE_ASSET_DESCRIPTION_MODAL, document.getElementById("changeAssetDescriptionModal")); ko.applyBindings(PAY_DIVIDEND_MODAL, document.getElementById("payDividendModal")); diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 71c41fcdd..b3dde3602 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -228,6 +228,7 @@ "issuance_exceed_max_quantity": "This issuance would exceed the hard limit for maximum quantity.", "you_will_be_issuing": "You will be issuing %s additional quantity on your token %s.", "you_have_issued": "You have issued %s additional quantity on your token %s.", + "you_have_reset": "You have reset %s with %s supply and now is %s.", "asset_will_be_transfered": "%s will be transferred to %s.", "asset_has_been_transfered": "%s has been transferred to %s.", "same_description_token": "This description is the same as the current description.", @@ -333,6 +334,7 @@ "notif_token_desc_changed": "Token %s had its description changed from %s to %s", "notif_additional_issued": "Additional %s units issued for token %s", "notif_token_issued": "Token %s was issued with an initial quantity of %s units", + "notif_token_reset": "Token %s was reset with a new supply of %s units and now it's %s", "notif_order_buy_active": "Your order to buy %s %s from %s in exchange for %s %s is active", "notif_order_matched": "Order matched between %s (gave %s %s) and %s (gave %s %s)", "notif_order_expired": "Your order ID %s from address %s has expired", @@ -353,6 +355,7 @@ "pend_or_unconf_lock": "%s lock of token %s against additional issuance", "pend_or_unconf_change_desc": "%s change of description for token %s to %s", "pend_or_unconf_issuance_add": "%s issuance of %s additional units for token %s", + "pend_or_unconf_reset": "%s reset of %s to %s supply units and it will be %s", "pend_or_unconf_issuance": "%s creation of token %s with initial quantity of %s units", "pend_or_unconf_broadcast": "%s broadcast:
Text: %s
Value: %s", "pend_or_unconf_bet": "%s %s bet on feed @ %s
Wager: %s XCP, Counterwager: %s XCP", @@ -536,8 +539,10 @@ "show_info": "Show Info", "burn_for_xcp": "Burn for XCP", "issue_additional": "Issue Additional", + "reset_token": "Reset Asset", "transfer_ownership": "Transfer Ownership", "lock_token_issuance": "Lock Token Issuance", + "reset_token_issuance": "Reset Token", "change_token_description": "Change Token Description", "issued": "Issued: %s", "change_address_label": "Change Address Label", @@ -575,6 +580,8 @@ "block_time": "Block Time", "divisible_token": "Divisible token?", "divisible_token_note": "Divisble assets can be subdivided into decimal places.", + "divisible": "divisible", + "not_divisible": "not divisible", "is_locked": "Is locked?", "is_locked_note": "Locked tokens may not have additional unit issued.", "pgp_signature": "PGP Signature", @@ -658,6 +665,7 @@ "pay_holders": "Use this form to pay holders of any token a distribution using XCP or any other token. Note that the full required balance of the token paid out must be present at this same address.

Please NOTE that this action is irreversible!", "address_transfer_ownership": "Enter the Bitcoin address you would like to permanently transfer ownership of this token to. (Be aware that this will not transfer the actual units of this token that you own to this address -- you can do that with a separate Send transaction.)

Please NOTE that this action is irreversible!", "more_token_issue": "How much more of this token would you like to issue? (For divisible tokens, state the quantity as a whole or floating point number, not in satoshis -- e.g. '732.45')

There are currently %s units of this token issued.

Please NOTE that this action is irreversible!", + "reset_token_issue": "Please, enter the new supply and indicate if the token will be divisible or not.

There are currently %s units of this token issued and the token is %s.", "asset_creation_fee_xcp": "Please note that a %s XCP fee will be deducted from your balance upon successful creation.", "change_token_description_p1": "This token's current description is:", "change_token_description_p2": "Enter a new description for your token", diff --git a/src/pages/balances.html b/src/pages/balances.html index bb685d4b9..6cdadd813 100644 --- a/src/pages/balances.html +++ b/src/pages/balances.html @@ -139,6 +139,7 @@

  • +
  • @@ -814,6 +815,64 @@

    + +