# Create Proxy Wallet

In Vortex we created fully non-custodial architecture, where only you have access to assets. To achieve this we created deterministic scheme to create proxy wallets.

To generate wallets you can use [#calculate-address](#calculate-address "mention") on Curra API, and verify that this address belongs to your Ownership ID with [#how-to-calculate-address-to-verify](#how-to-calculate-address-to-verify "mention"), so assets from these wallets can be transferred only to your Ombibus wallets, whitelisted in [rules](https://docs.curra.io/curra-documentation/vortex/rules "mention") smart contract, ensuring security of your assets.

{% hint style="info" %}
Every address is generated from unique salt (can be considered an unique identifier) and addresses remain the same across different EVM chains if their salts are equal. This means you can create the same addresses across multiple EVM blockchains.
{% endhint %}

<details>

<summary>How to calculate and verify address? (Advanced)</summary>

Addresses are fully deterministic and non-custodial. [Gas Pump](https://docs.curra.io/curra-documentation/vortex/gas-pump) address is used as seed. After [Ownership NFT](https://docs.curra.io/curra-documentation/vortex/ownership-nft) is minted, addresses become immutable (this happens when first deposit is forwarded to Omnibus wallet) and only the NFT holder can change the [Rule smart contract](https://docs.curra.io/curra-documentation/vortex/rules)

Address calculation can defer on different platform / programming languages, but general algorithm is the following:

Calculate [Ownership NFT](https://docs.curra.io/curra-documentation/vortex/ownership-nft) identifier:

<pre class="language-solidity" data-full-width="true"><code class="lang-solidity"><strong>gasPumpAddress = "0x............"
</strong>presetsAddress = "0x............"
<strong>ownershipId = uint256(keccak256(abi.encodePacked(address(presetsAddress), keccak256(abi.encodepacked(gasPumpAddress)))))
</strong></code></pre>

Calculate Rule upgradable proxy address:

<pre class="language-solidity" data-full-width="true"><code class="lang-solidity"><strong>// abi is predictProxyAddress(uint256), proxy address is upgradable proxy of the Rule smart contract
</strong><strong>proxyAddress = curraContract.predictProxyAddress(ownershipId)
</strong></code></pre>

Calculate forwarder implementation address which is going to be used to generate clones, aka proxy wallets

<pre class="language-typescript"><code class="lang-typescript"><strong>forwarderImplInitcode = "60a03461008b57601f61082c38819003918201601f19168301916001600160401b038311848410176100905780849260209460405283398101031261008b57516001600160a01b038116810361008b5760805260405161078590816100a7823960805181818160880152818160e801528181610172015281816101fc0152818161027d01526103c40152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080806040526004361015610022575b50361561001857005b61002061036b565b005b600090813560e01c90816325e3d522146102335750806358843b36146101ad5780637d76ccf114610117578063b41b08c2146100c15763d87108d00361000f57346100be57610070366102c9565b9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036100ba576100b79261062d565b80f35b8380fd5b80fd5b50346100be576100d0366102c9565b9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036100ba576100b792610554565b50346100be5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100be5761014f6102a1565b60643573ffffffffffffffffffffffffffffffffffffffff80821682036100ba577f00000000000000000000000000000000000000000000000000000000000000001633036101a9576100b79160443590602435906106bc565b8280fd5b50346100be5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100be576101e56102a1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361022f576100b7906024359061052e565b5080fd5b90503461022f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022f5760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff821682036102c457565b600080fd5b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60609101126102c45773ffffffffffffffffffffffffffffffffffffffff60043581811681036102c457916024359160443590811681036102c45790565b67ffffffffffffffff811161033c57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604080517f8fab1a0600000000000000000000000000000000000000000000000000000000815230600482015247602482015260006044820181905273ffffffffffffffffffffffffffffffffffffffff9083836064817f000000000000000000000000000000000000000000000000000000000000000086165afa9283156104b45781948294610410575b50505082161561040c5761040a916104c0565b565b5050565b919450919250803d82116104ad575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f820116830183811067ffffffffffffffff8211176104805782528201829003126101a95780519282841684036100be575060200151903880806103f7565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b503d61041f565b508351903d90823e3d90fd5b600080809381935af1156104d057565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152fd5b9073ffffffffffffffffffffffffffffffffffffffff82161561040c5761040a916104c0565b91909173ffffffffffffffffffffffffffffffffffffffff80921680156106275760008093604493602096604051947fa9059cbb00000000000000000000000000000000000000000000000000000000865260048601526024850152165af13d15601f3d11600160005114161716156105c957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152fd5b50505050565b909173ffffffffffffffffffffffffffffffffffffffff809116918215610627571691823b156102c45760646000928360405195869485937f42842e0e000000000000000000000000000000000000000000000000000000008552306004860152602485015260448401525af180156106b0576106a75750565b61040a90610328565b6040513d6000823e3d90fd5b919273ffffffffffffffffffffffffffffffffffffffff8091169283156107485716803b156102c4576000928360c49260405196879586947ff242432a00000000000000000000000000000000000000000000000000000000865230600487015260248601526044850152606484015260a060848401528160a48401525af180156106b0576106a75750565b505050505056fea26469706673582212207adce9e6f6f4860d32d895a3080819821d79bea7e3699d0e3d8c4deb4aae60d064736f6c63430008120033"
</strong><strong>const forwarderImplementationAddress = getCreate2Address(
</strong>  ownershipNFTAddress, // deployer
  ownershipId, // salt
  forwarderImplInitcode, // initcode
);
</code></pre>

Calculate [proxy wallet](https://docs.curra.io/curra-documentation/features/broken-reference) address:

{% code fullWidth="true" %}

```typescript
salt = "0000000000000000" // 8 byes
forwarderImplAddressBytes = strip0x(forwarderImplementationAddress)
proxyInitcode = `0x602c3d8160093d39f33d3d3d3d363d3d37363d73${forwarderImplAddressBytes}5af43d3d93803e602a57fd5bf3`;
proxyInitcodeHash = keccak256(proxyInitcode);
forwarderAddress = getCreate2Address(
  proxyAddress,
  salt,
  proxyInitcodeHash,
);
```

{% endcode %}

`forwarderAddress` is the address of [the proxy wallet](https://docs.curra.io/curra-documentation/features/broken-reference).&#x20;

</details>

## Allocate address

<mark style="color:green;">`POST`</mark> `https://api.curra.io/addresses`

This method uses random `salt` to calculate next address.&#x20;

#### Headers

| Name                                           | Type             | Description |
| ---------------------------------------------- | ---------------- | ----------- |
| content-type<mark style="color:red;">\*</mark> | application/json |             |
| x-api-key<mark style="color:red;">\*</mark>    | your\_api\_key   |             |

#### Request Body

| Name                                          | Type      | Description                                        |
| --------------------------------------------- | --------- | -------------------------------------------------- |
| blockchains<mark style="color:red;">\*</mark> | string\[] | \["ETHEREUM", "SMART\_CHAIN", "POLYGON", "GOERLI"] |
| uniqueId                                      | string    | minLength: 1, maxLength: 100                       |
| meta                                          | string    | minLength: 1, maxLength: 500                       |

{% tabs %}
{% tab title="200: OK " %}

```json
[
    {
    "value": "string",
    "id": "string",
    "blockchain": "ETHEREUM",
    "uniqueId": "string",
    "meta": "string",
    "timestamp": 0
  }
]
```

{% endtab %}

{% tab title="500: Internal Server Error " %}

```json
{
  "message": "string",
  "error": "ADDRESSES_ARE_DIFFERENT"
}
```

{% endtab %}
{% endtabs %}

### You can find complete [**API Reference here**](https://api.curra.io/documentation/). <a href="#sdk" id="sdk"></a>

### SDK <a href="#sdk" id="sdk"></a>

```js
import { Blockchain } from "@curra/sdk";

// just new addresses
// NOTICE: returns two identical addresses created in two different EVM blockchains
const addresses = await curra.createAddresses({
    blockchains: [Blockchain.ETHEREUM, Blockchain.SMART_CHAIN],
});

// new address with additional fields
const [address] = await curra.createAddresses({
    blockchains: [Blockchain.ETHEREUM],
    uniqueId: "I'm unique", // optional unique id
    meta: "my user id?", // custom data can be linked to the address, will be included in  incomes webhooks
});
```
