GalaConnect API

GalaConnect is Gala's public programmatic surface for GalaSwap: fetching and filling token swaps, creating and terminating swaps, creating headless wallets, creating project tokens, authorizing cross-channel fees, and proxying GalaChain token-contract calls across channels. Documented as OpenAPI 3.0 and labelled Beta.

OpenAPI Specification

gala-games-galaconnect-openapi.json Raw ↑
{
  "openapi": "3.0.0",
  "info": {
    "version": "1.0.0",
    "title": "GalaConnect API Beta",
    "description": "# Getting Started\n\nGalaConnect offers a public API for programmatic use cases.\n\nThe base URI for all requests is `https://api-galaswap.gala.com`.\n\n## Authentication\n\nUsing the GalaConnect API requires a Gala account, which can be created at [games.gala.com](https://games.gala.com).\n\nYou must have your GalaChain wallet address, private key, and public key, in order to use the API.\n\nAny write operation (creating swaps, accepting swaps, terminating swaps) via the API needs the following in order to be accepted by GalaChain:\n\n1. Your GalaChain wallet address as an `X-Wallet-Address` header.\n2. Your GalaChain public key as a `signerPublicKey` property in the request body, in base64 encoding.\n3. A signature for the request body signed with your private key, as a `signature` property in the request body.\n\n### Creating a Wallet\n\nAfter creating an account on [games.gala.com](https://games.gala.com), visit [account settings](https://games.gala.com/account?component=GyriPassphrase) and follow the instructions to create a GalaChain \"transfer code\", which also initializes your GalaChain wallet. Keep your transfer code safe and secure. You will need it in the next step.\n\n### Getting your Private Key\n\nOnce you have a GalaChain wallet, visit [account settings](https://games.gala.com/account?component=GalaChainPrivateKey&plaintext) and download your GalaChain private key. Note that this link has a `&plaintext` query parameter to trigger it to download your private key in plaintext as an advanced user. This key is used to sign requests to the GalaConnect API. Your key will be downloaded in a text file which will also contain your GalaChain wallet address, which will look something like `client|123456789abcdef012345678`, and which you should provide in API requests as the `X-Wallet-Address` header.\n\n### Getting your Public Key\n\nTo get your public key, you can make the following request to the GalaConnect API, substituting your GalaChain wallet address for `YOUR_WALLET_ADDRESS_HERE`:\n\n```bash\ncurl --request POST \\\n  --url https://api-galaswap.gala.com/galachain/api/asset/public-key-contract/GetPublicKey \\\n  --header 'Content-Type: application/json' \\\n  --data '{\"user\": \"YOUR_WALLET_ADDRESS_HERE\"}'\n```\n\nYour public key will be returned as a base64 encoded string in the response body. It will look something like `Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY`. For any request that requires a signature, you must include your public key in the request body as a `signerPublicKey` property.\n\n### Request Signing\n\nAny request to the GalaConnect API that executes a write operation (creating swaps, accepting swaps, terminating swaps) must be signed using your GalaChain private key with a secp256k1 signature.\n\nTo calculate the signature for a request, first recursively order the properties of the request body alphabetically by name. Then, stringify the object to a minimal JSON string. Use your private key to calculate the signature on the keccak256 hash of the stringified object. The signature must be [normalized](https://wiki.hyperledger.org/display/BESU/SECP256R1+Support) such that it's less than or equal to half of the secp256k1 curve's order n. Provide the signature in the request body as a property named \"signature\".\n\nHere is TypeScript code that demonstrates how to correctly implement signing in Node.js:\n\n```js\nimport stringify from 'json-stringify-deterministic';\nimport ellipticPkg from 'elliptic';\nimport jsSha3Pkg from 'js-sha3';\nimport BN from 'bn.js';\n\nconst { keccak256 } = jsSha3Pkg;\nconst { ec: EC } = ellipticPkg;\nconst ecSecp256k1 = new EC('secp256k1');\n\nexport function signObject<TInputType extends object>(\n  obj: TInputType,\n  privateKey: string\n): TInputType & { signature: string } {\n  const toSign = { ...obj };\n\n  if ('signature' in toSign) {\n    delete toSign.signature;\n  }\n\n  const stringToSign = stringify(toSign);\n  const stringToSignBuffer = Buffer.from(stringToSign);\n\n  const keccak256Hash = Buffer.from(keccak256.digest(stringToSignBuffer));\n  const privateKeyBuffer = Buffer.from(privateKey.replace(/^0x/, ''), 'hex');\n\n  const signature = ecSecp256k1.sign(keccak256Hash, privateKeyBuffer);\n\n  // Normalize the signature if it's greater than half of order n\n  if (signature.s.cmp(ecSecp256k1.curve.n.shrn(1)) > 0) {\n    const curveN = ecSecp256k1.curve.n;\n    const newS = new BN(curveN).sub(signature.s);\n    const newRecoverParam = signature.recoveryParam != null ? 1 - signature.recoveryParam : null;\n    signature.s = newS;\n    signature.recoveryParam = newRecoverParam;\n  }\n\n  const signatureString = Buffer.from(signature.toDER()).toString('base64');\n\n  return {\n    ...toSign,\n    signature: signatureString,\n  };\n}\n```\n\nFor example, if your private key were `0x0000000000000000000000000000000000000000000000000000000000000001`, then a request body with the following content:\n\n```js\n{\n  \"gala\": \"swap\",\n  \"is\": \"a\",\n  \"decentralized\": \"exchange\",\n  \"on\": \"galachain\",\n  \"uniqueKey\": \"galaconnect-operation-dcdb4974-328b-440b-837d-ed53d80e60dd\",\n  \"signerPublicKey\": \"Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY\"\n}\n```\n\nWould have the signature `MEQCIExBcdA40VmP3a/efnM6J3E/VyN3HgTTXXXsMVPsc3sWAiBIxFesuT74Ge2PWoyrmIcual4UZGO8D8GgNDor93d26Q==`, and the operation would be sent in the request body to the GalaConnect API as follows:\n\n```js\n{\n  \"gala\": \"swap\",\n  \"is\": \"a\",\n  \"decentralized\": \"exchange\",\n  \"on\": \"galachain\",\n  \"uniqueKey\": \"galaconnect-operation-dcdb4974-328b-440b-837d-ed53d80e60dd\",\n  \"signerPublicKey\": \"Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY\",\n  \"signature\": \"MEQCIExBcdA40VmP3a/efnM6J3E/VyN3HgTTXXXsMVPsc3sWAiBIxFesuT74Ge2PWoyrmIcual4UZGO8D8GgNDor93d26Q==\"\n}\n```\n\n### Unique Key\n\nAll write operations require a `uniqueKey` in the request body, as shown in the example above. The uniqueKey should be prefixed with `galaconnect-operation-`. The rest is up to you, but must be globally unique. Using a UUID is a good choice. This key is used to prevent replay attacks and potential repeat submission of operations in the case of retries. GalaChain will not permit two transactions with the same uniqueKey to commit to the chain.\n\n### Headless Wallet\n\nInstead of creating a full Gala platform account on games.gala.com, it is also possible to create a \"headless\" wallet via the GalaConnect API if you prefer, by using the `CreateHeadlessWallet` endpoint. You must provide a public key for the new wallet (unlike elsewhere in the API, you must provide the public key here in lowercase hexadecimal encoding, preceded by `0x`).\n\nTo generate an address and keys for your new headless wallet, the following JavaScript code using the `ethers` library in Node.js will work:\n\n```js\nconst ethers = require('ethers');\nconst newWallet = ethers.Wallet.createRandom();\nconsole.log('Public key:', newWallet.publicKey);\nconsole.log('Private key:', newWallet.privateKey);\nconsole.log('X-Wallet-Address', `eth|${newWallet.address.replace('0x', '')}`);\n```\n\nBe sure to keep your private key safe and secure as it cannot be recovered if lost.\n\nCreating a headless wallet is effectively the same as connecting a Web3 wallet to the GalaConnect website client, and you can use headless wallets and Web3 wallets interchangeably with both the GalaConnect API and website client.\n\n## Uses\n\nSwaps on GalaChain have a concept of `uses`, representing a division of the swap into discrete units that can be accepted separately. For example, a swap may offer 1000 $GALA for 2000 $SILK with five uses. When accepting this swap via the `BatchFillTokenSwap` endpoint, you may choose to use between one and five of those uses. If you choose to use all five uses, then you will receive 5000 $GALA in exchange for 10000 $SILK. If you choose to use only two uses, then you will receive 2000 $GALA in exchange for 4000 $SILK.\n\nA swap remains active on GalaConnect until all of its uses have been accepted (or its creator terminates it). If a swap has already had two of its five uses accepted, then you can only accept up to the remaining three uses (which would be 3000 $GALA for 6000 $SILK in this case). You can determine how many uses of a swap have already been used by checking the `usesSpent` property returned from the `FetchAvailableTokenSwaps` endpoint.\n\nWhen creating swaps via the API, it's best to create swaps with tiny quantity and huge number of uses. This makes your swap more flexible for swappers who may have a very specific amount of tokens they want to swap. When swaps are created via the GalaConnect website client, the quantities and uses are automatically optimized for the swap creator, so swaps created via the website client will always have low quantity and high uses.\n\nThe GalaConnect website client uses TypeScript code similar to the following to automatically optimize quantity and uses:\n\n```js\nimport BigNumber from 'bignumber.js';\n\nconst greatestCommonDivisor = (a: BigNumber, b: BigNumber): BigNumber =>\n  a.isZero() ? b : greatestCommonDivisor(b.mod(a), a);\n\nexport function calculateSwapQuantitiesAndUsesValues(\n  givingTokenDecimals: number,\n  receivingTokenDecimals: number,\n  givingTokenAmount: BigNumber,\n  receivingTokenAmount: BigNumber,\n) {\n  const givingTokenQuantumAmount = BigNumber(\n    givingTokenAmount.toFixed(givingTokenDecimals, BigNumber.ROUND_FLOOR),\n  ).multipliedBy(BigNumber(10).pow(givingTokenDecimals));\n\n  const receivingTokenQuantumAmount = BigNumber(\n    receivingTokenAmount.toFixed(receivingTokenDecimals, BigNumber.ROUND_FLOOR),\n  ).multipliedBy(BigNumber(10).pow(receivingTokenDecimals));\n\n  const gcd = greatestCommonDivisor(givingTokenQuantumAmount, receivingTokenQuantumAmount);\n\n  const givingTokenQuantity = givingTokenQuantumAmount\n    .dividedBy(gcd)\n    .dividedBy(BigNumber(10).pow(givingTokenDecimals));\n\n  const receivingTokenQuantity = receivingTokenQuantumAmount\n    .dividedBy(gcd)\n    .dividedBy(BigNumber(10).pow(receivingTokenDecimals));\n\n  const uses = gcd;\n\n  return {\n    givingTokenQuantity,\n    receivingTokenQuantity,\n    uses,\n  };\n}\n```\n\nFor example if we want to swap a total of 1000 $GALA for 2000 $SILK (both of which have 8 decimals places), then the inputs to this function are `8, 8, 1000, 2000` and the output is:\n\n```js\n{\n  \"givingTokenQuantity\": \"0.00000001\",\n  \"receivingTokenQuantity\": \"0.00000002\",\n  \"uses\": \"100000000000\"\n}\n```\n\nIf we create a new swap with these parameters, then swappers can choose exactly how much they want to swap, with such high granularity that they can effectively swap any amount of $SILK they want up to the total swap size of 2000.\n\nNote that the ability to break down swaps with high granularity requires that the swap creator not have an excessively precise total quantity that they want to swap. For example if we call this function with parameters `8, 8, 1000.00000001, 2000.00000001` then we cannot break that down at all, and the output is:\n\n```js\n{\n  \"givingTokenQuantity\": \"1000.00000001\",\n  \"receivingTokenQuantity\": \"2000.00000001\",\n  \"uses\": \"1\"\n}\n```\n\nIt is advisable to round your total quantities to use no more than four decimal places less than the maximum number of decimal places supported by the tokens you are swapping. For example, use no more than four decimal places when creating swaps for tokens that support up to eight decimal places, such as $GALA and $SILK. This guarantees that any swap you create can have at least ten thousand uses.\n\n## GalaChain Fees\n\nSome GalaChain operations have fees associated with them. To get the current GalaChain fees for any operation, make a request as you normally would, but add `/fee` to the end of the path. You should also omit the `signature` and `uniqueKey` fields from the request body.\n\nThe `/fee` routes are not explicitly listed in the route reference below, but the previously described logic applies to all routes. Note that the fee to create a project token is a separate concept. That fee is not a chaincode fee and is levied in addition to the chaincode fees returned by the `/v1/CreateProjectToken/fee` route (if any).\n\nAs an example, to get the GalaChain fees for creating a swap, make a `POST` request to `https://api-galaswap.gala.com/v1/RequestTokenSwap/fee`. Here is an example of what this endpoint will return:\n\n```js\n{\n  \"fees\": [\n    {\n      \"type\": \"galachain_automatic\",\n      \"operationDto\": {\n        \"offered\": [\n          {\n            \"quantity\": \"10\",\n            \"tokenInstance\": {\n              \"collection\": \"SILK\",\n              \"category\": \"Unit\",\n              \"type\": \"none\",\n              \"additionalKey\": \"none\",\n              \"instance\": \"0\"\n            }\n          }\n        ],\n        \"wanted\": [\n          {\n            \"quantity\": \"20\",\n            \"tokenInstance\": {\n              \"collection\": \"GALA\",\n              \"category\": \"Unit\",\n              \"type\": \"none\",\n              \"additionalKey\": \"none\",\n              \"instance\": \"0\"\n            }\n          }\n        ],\n        \"uses\": \"1\"\n      },\n      \"operationName\": \"RequestTokenSwap\",\n      \"galaChainMethod\": \"RequestTokenSwap\",\n      \"channel\": \"asset\",\n      \"fee\": \"1\",\n      \"feeInGala\": \"1\",\n      \"feeToken\": \"GALA|Unit|none|none\"\n    }\n  ]\n}\n```\n\nThe fee amount in this example is `1` $GALA, as read from the `feeInGala` field. Some operations may return multiple fees, which you can sum together for the total fee. Fees are always in $GALA.\n\nThere are two `type`s of fees and they must be treated quite differently:\n\n### galachain_automatic\n\nYou do not need to do anything special to pay this fee. It is automatically deducted from your wallet balance when you submit your operation and it commits to GalaChain.\n\n### galachain_cross_channel_authorization\n\nThis type of fee must be paid manually and is levied for certain operations on channels besides the asset channel. You will not encounter this type of fee if you only operate on tokens that are swappable on GalaConnect. However you may encounter this type of fee if you use the `/galachain/` endpoints to operate on NFTs, which often exist on channels other than the asset channel.\n\nTo pay the `feeInGala` in such cases, you must make a request to the `/v1/channels/{channel}/AuthorizeFee` endpoint documented below. Making a request to this endpoint will burn $GALA on the asset channel, and give you a fee credit on the target channel. You can then carry out your operation on the target channel. You may also batch and pay this fee in advance if you choose to. For example if you know that you need to transfer ten NFTs and you know that each transfer will cost one $GALA, you may make a single request to `/v1/channels/{channel}/AuthorizeFee` to authorize a fee of ten $GALA, and then you can perform the ten transfers.\n\n## Rate Limiting\n\nThe GalaConnect API has a global rate limit of 20 requests per every 10 seconds. If you exceed the limit, you will receive a `429 Too Many Requests` response. The response will contain a `Retry-After` header indicating the number of seconds you must wait before making another request. For example if you must wait 5 seconds before making another request, the API will send a 429 response containing a `Retry-After` header whose value is `5`.\n\nIn addition, you should avoid performing write operations (such as creating swaps) concurrently, as concurrent transactions affecting the same wallet may result in serialization failures, which would be returned as a `409 Conflict` response.\n\nThe rate limiting policy is subject to change, thus code that uses the API should be prepared for the possibility of being rate limited. If you need a higher rate limit, please contact support@gala.com.\n\n## Errors\n\nThe GalaConnect API returns two classes of errors:\n\n### GalaConnect Errors\n\nGalaConnect errors are errors that occur in GalaConnect's application code, as opposed to GalaChain chaincode. GalaConnect errors will always be returned as an object with:\n\n1. An `error` property containing an error code, such as `INVALID_BODY`.\n2. An `errorId` property with a unique ID for the error. You should record and share this ID with Gala support if you need assistance with the error.\n\nErrors may also contain additional properties with more specific information, such as request validation failure details.\n\n### GalaChain Errors\n\nGalaChain errors are returned when GalaChain chaincode encounters an error, which is then bubbled up through the GalaConnect application and back to you. GalaChain errors will be returned as an object with:\n\n1. A `message` property containing a description of the error.\n2. An `error` property containing an object with more details about the error, including an `ErrorKey` property with a specific error code.\n3. An `errorId` property with a unique ID for the error. You should record and share this ID with Gala support if you need assistance with the error.\n\n## Undocumented Response Properties\n\nSome endpoints may return additional properties that are not documented here. Such properties are not guaranteed to be stable and should not be relied upon in your application.\n\n# API Recipes\n\nLet's look at example requests for some common operations. For all of these requests we are using this wallet:\n\n1. Wallet address: `client|123456789abcdef012345678`\n2. Public key: `Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY`\n3. Private key: `0x0000000000000000000000000000000000000000000000000000000000000001`\n\nThis is not a real wallet, so making these requests verbatim will fail. You would need to use your own credentials in place of the above. You would also need to provide a different `uniqueKey` that is globally unique.\n\nThe signatures in the examples are however correct (using the private key shown above and the `uniqueKey` shown in the request body), so you can use them as a reference to help validate your signing code.\n\n## Fetch Available $GALA to $SILK Swaps\n\nLet's get a list of swaps where we can trade our $GALA for another wallet's $SILK.\n\n```js\nfetch('https://api-galaswap.gala.com/v1/FetchAvailableTokenSwaps', {\n  method: 'POST',\n  headers: {\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    offeredTokenClass: {\n      collection: 'GALA',\n      category: 'Unit',\n      type: 'none',\n      additionalKey: 'none',\n    },\n    wantedTokenClass: {\n      collection: 'SILK',\n      category: 'Unit',\n      type: 'none',\n      additionalKey: 'none',\n    },\n  }),\n});\n```\n\nResponse:\n\n```js\n{\n  \"results\": [\n    {\n      \"offeredTokenClass\": \"SILK|Unit|none|none\",\n      \"wantedTokenClass\": \"GALA|Unit|none|none\",\n      \"created\": 1712230114698,\n      \"expires\": 0,\n      \"offered\": [\n        {\n          \"quantity\": \"192\",\n          \"tokenInstance\": {\n            \"additionalKey\": \"none\",\n            \"category\": \"Unit\",\n            \"collection\": \"SILK\",\n            \"instance\": \"0\",\n            \"type\": \"none\"\n          }\n        }\n      ],\n      \"offeredBy\": \"client|222222222222222222222222\",\n      \"swapRequestId\": \"\\u0000GCTSR\\u00001712230114698\\u00004e4c85d5f313ff871d2d677ac72d52c8cfc748bdc821f9d4a3f57395eec9d6c9\\u0000\",\n      \"uses\": \"1\",\n      \"usesSpent\": \"0\",\n      \"wanted\": [\n        {\n          \"quantity\": \"68\",\n          \"tokenInstance\": {\n            \"additionalKey\": \"none\",\n            \"category\": \"Unit\",\n            \"collection\": \"GALA\",\n            \"instance\": \"0\",\n            \"type\": \"none\"\n          }\n        }\n      ]\n    }\n  ]\n}\n```\n\n## Accept a Swap\n\nLet's accept the swap we found in the previous example. This request requires authentication.\n\n```js\nfetch('https://api-galaswap.gala.com/v1/BatchFillTokenSwap', {\n  method: 'POST',\n  headers: {\n    'Content-Type': 'application/json',\n    'X-Wallet-Address': 'client|123456789abcdef012345678',\n  },\n  body: JSON.stringify({\n    swapDtos: [\n      {\n        swapRequestId:\n          '\\u0000GCTSR\\u00001712230114698\\u00004e4c85d5f313ff871d2d677ac72d52c8cfc748bdc821f9d4a3f57395eec9d6c9\\u0000',\n        uses: '1',\n        expectedTokenSwap: {\n          wanted: [\n            {\n              quantity: '68',\n              tokenInstance: {\n                additionalKey: 'none',\n                category: 'Unit',\n                collection: 'GALA',\n                instance: '0',\n                type: 'none',\n              },\n            },\n          ],\n          offered: [\n            {\n              quantity: '192',\n              tokenInstance: {\n                additionalKey: 'none',\n                category: 'Unit',\n                collection: 'SILK',\n                instance: '0',\n                type: 'none',\n              },\n            },\n          ],\n        },\n      },\n    ],\n    uniqueKey: 'galaconnect-operation-1',\n    signerPublicKey: 'Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY',\n    signature:\n      'MEQCIEtyGcJDz9ulqt5Uk+epQbcZWFkwxBVRuLO/wcg3oUhBAiAOPDHZF8h5Sb5oUt5z1AWNqUWJcFsQBkUMt7ReEIZ22w==',\n  }),\n});\n```\n\n## Create a Swap\n\nLet's create a swap where we offer 1000 $GALA for 2000 $SILK. This request requires authentication.\n\n```js\nfetch('https://api-galaswap.gala.com/v1/RequestTokenSwap', {\n  method: 'POST',\n  headers: {\n    'Content-Type': 'application/json',\n    'X-Wallet-Address': 'client|123456789abcdef012345678',\n  },\n  body: JSON.stringify({\n    offered: [\n      {\n        quantity: '1000',\n        tokenInstance: {\n          collection: 'GALA',\n          category: 'Unit',\n          type: 'none',\n          additionalKey: 'none',\n          instance: '0',\n        },\n      },\n    ],\n    wanted: [\n      {\n        quantity: '2000',\n        tokenInstance: {\n          collection: 'SILK',\n          category: 'Unit',\n          type: 'none',\n          additionalKey: 'none',\n          instance: '0',\n        },\n      },\n    ],\n    uses: '1',\n    uniqueKey: 'galaconnect-operation-1',\n    signerPublicKey: 'Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY',\n    signature:\n      'MEUCIQDdwEEGoLF/2pZizVeAeQGl3wBALQw1Dbh/4R6QR3RTiQIgFEwt1K+GgzhGyh6vPyEt8XF24u0d1pCOz78ct3Yhk7k=',\n  }),\n});\n```\n\nResponse:\n\n```js\n{\n  \"Status\": 1,\n  \"Data\": {\n    \"created\": 1712241257995,\n    \"expires\": 0,\n    \"fillIds\": [],\n    \"offered\": [\n      {\n        \"quantity\": \"1000\",\n        \"tokenInstance\": {\n          \"additionalKey\": \"none\",\n          \"category\": \"Unit\",\n          \"collection\": \"GALA\",\n          \"instance\": \"0\",\n          \"type\": \"none\"\n        }\n      }\n    ],\n    \"offeredBy\": \"client|123456789abcdef012345678\",\n    \"swapRequestId\": \"\\u0000GCTSR\\u00001712241257995\\u0000f096cfda086df84a8ee38980b2c14cc9785930bf66dcf3e0448d661127e369b7\\u0000\",\n    \"txid\": \"f096cfda086df84a8ee38980b2c14cc9785930bf66dcf3e0448d661127e369b7\",\n    \"uses\": \"1\",\n    \"usesSpent\": \"0\",\n    \"wanted\": [\n      {\n        \"quantity\": \"2000\",\n        \"tokenInstance\": {\n          \"additionalKey\": \"none\",\n          \"category\": \"Unit\",\n          \"collection\": \"SILK\",\n          \"instance\": \"0\",\n          \"type\": \"none\"\n        }\n      }\n    ]\n  }\n}\n```\n\n## Fetch the Fee to Terminate a Swap\n\nLet's check if there is a fee to terminate (cancel) the swap that we just created.\n\n```js\nfetch('https://api-galaswap.gala.com/v1/TerminateTokenSwap/fee', {\n  method: 'POST',\n  headers: {\n    'Content-Type': 'application/json',\n    'X-Wallet-Address': 'client|123456789abcdef012345678',\n  },\n  body: JSON.stringify({\n    swapRequestId:\n      '\\u0000GCTSR\\u00001712241257995\\u0000f096cfda086df84a8ee38980b2c14cc9785930bf66dcf3e0448d661127e369b7\\u0000',\n    signerPublicKey: 'Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY',\n  }),\n});\n```\n\nResponse:\n\n```js\n{\n  \"fees\": [\n    {\n      \"type\": \"galachain_automatic\",\n      \"operationDto\": {\n        \"swapRequestId\": \"GCTSR1710792378701ce0ec09292994e537eda883d8c40668a17641cb085d4c1fee8816ef41d91560e\"\n      },\n      \"operationName\": \"TerminateTokenSwap\",\n      \"galaChainMethod\": \"TerminateTokenSwap\",\n      \"channel\": \"asset\",\n      \"fee\": \"0\"\n      \"feeToken\": \"GALA|Unit|none|none\"\n    }\n  ]\n}\n```\n\nThe fee is zero $GALA.\n\n## Terminate a Swap\n\nLet's go ahead and terminate (cancel) the above swap that we just created.\n\n```js\nfetch('https://api-galaswap.gala.com/v1/TerminateTokenSwap', {\n  method: 'POST',\n  headers: {\n    'Content-Type': 'application/json',\n    'X-Wallet-Address': 'client|123456789abcdef012345678',\n  },\n  body: JSON.stringify({\n    swapRequestId:\n      '\\u0000GCTSR\\u00001712241257995\\u0000f096cfda086df84a8ee38980b2c14cc9785930bf66dcf3e0448d661127e369b7\\u0000',\n    uniqueKey: 'galaconnect-operation-1',\n    signerPublicKey: 'Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY',\n    signature:\n      'MEUCIQDqI9xkV2tocjBzpLMqI0WwFkVlieMaOt/nFIoSq9uoRgIgIcbGQ7kwXre2SDFOow62AoIc9Z9TfdZtiLE/cNEUDcI=',\n  }),\n});\n```\n",
    "x-logo": {
      "url": "https://connect.gala.com/img/hero-image.png",
      "backgroundColor": "rgb(18, 18, 18)",
      "altText": "GalaConnect logo"
    }
  },
  "paths": {
    "theme": {
      "openapi": {
        "theme": {
          "codeBlock": {
            "tokens": {
              "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
            }
          },
          "components": {
            "buttons": {
              "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
            },
            "httpBadges": {
              "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
            }
          },
          "sidebar": {
            "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji",
            "backgroundColor": "rgb(18, 18, 18)",
            "textColor": "white"
          },
          "rightPanel": {
            "textColor": "white",
            "backgroundColor": "rgb(18, 18, 18)"
          },
          "typography": {
            "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji",
            "fieldName": {
              "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
            },
            "links": {
              "color": "#0090cc"
            },
            "heading1": {
              "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
            },
            "heading2": {
              "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
            },
            "heading3": {
              "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
            },
            "headings": {
              "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
            },
            "rightPanelHeading": {
              "fontFamily": "Figtree,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
            }
          }
        }
      }
    },
    "/v1/tokens": {
      "get": {
        "tags": [
          "API: GalaConnect Operations"
        ],
        "summary": "Get Tokens",
        "description": "Get a list of tokens available on GalaConnect. By default, only \"trending\" tokens are returned. To get other tokens, use the `searchprefix` query parameter to search for them. Note that price information is not guaranteed, and the `currentPrices` property may be an empty object. Token prices are sourced from CoinGecko when possible. For project tokens (created by GalaConnect users) the price shown will be a historical average of the price that the token has been swapped at on GalaConnect. If there is no swap history yet for a project token, then its price will be assigned based on the amount of $GALA the creator burned to create it.",
        "parameters": [
          {
            "in": "query",
            "name": "searchprefix",
            "schema": {
              "type": "string"
            },
            "description": "Perform a case-insensitive prefix search for tokens. The searched fields for each token are `symbol`, `name`, `priceSymbol`."
          },
          {
            "in": "query",
            "name": "symbols",
            "schema": {
              "type": "string"
            },
            "description": "A comma-separated list of token symbols to fetch. If provided, only tokens with these symbols will be returned."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "tokens"
                  ],
                  "properties": {
                    "tokens": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SwappableToken"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/FetchAvailableTokenSwaps": {
      "post": {
        "tags": [
          "API: GalaConnect Operations"
        ],
        "summary": "Get Swaps",
        "description": "Get a list of available swaps for the provided token pair. The `wantedTokenClass` should be the token that you want to receive, and the `offeredTokenClass` should be the token that you are willing to give in exchange. Up to 100 results are returned, ordered such that the ones with the best exchange rate (for you) come first. Note that in the response body, the perspective and meaning of \"offered\" and \"wanted\" is reversed compared to the request body. The \"offered\" field in the response is what the swap creator is offering, and the \"wanted\" field is what they want from you in exchange.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "offeredTokenClass",
                  "wantedTokenClass"
                ],
                "properties": {
                  "offeredTokenClass": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/TokenClass"
                      },
                      {
                        "type": "object",
                        "required": [
                          "collection"
                        ],
                        "properties": {
                          "collection": {
                            "type": "string",
                            "example": "SILK"
                          }
                        }
                      }
                    ]
                  },
                  "wantedTokenClass": {
                    "$ref": "#/components/schemas/TokenClass"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "results"
                  ],
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Swap"
                      }
                    }
  

# --- truncated at 32 KB (152 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/gala-games/refs/heads/main/openapi/gala-games-galaconnect-openapi.json