This repository has been archived by the owner on Feb 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement SEP-8 helper to get approval server url (#210)
What This PR implements the final helper function to get the approval server's url from the stellar.toml file at the issuer's home domain. It also piggybacks a test enhancement for the getRegulatedAssetsInTx. Why Approval Provider relies on a valid approval server URL for initialization.
- Loading branch information
Showing
5 changed files
with
233 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
import axios from "axios"; | ||
import sinon from "sinon"; | ||
import { Config } from "stellar-sdk"; | ||
import { getApprovalServerUrl } from "./getApprovalServerUrl"; | ||
|
||
describe("getApprovalServerUrl", () => { | ||
let axiosMock: sinon.SinonMock; | ||
|
||
beforeEach(() => { | ||
axiosMock = sinon.mock(axios); | ||
Config.setDefault(); | ||
}); | ||
|
||
afterEach(() => { | ||
axiosMock.verify(); | ||
axiosMock.restore(); | ||
}); | ||
|
||
test("Issuer's Home Domain missing", async () => { | ||
try { | ||
// @ts-ignore | ||
const res = await getApprovalServerUrl({ | ||
asset_code: "USD", | ||
asset_issuer: | ||
"GDBMMVJKWGT2N6HZ2BGMFHKODASVFYIHL2VS3RUTB3B3QES2R6YFXGQW", | ||
}); | ||
expect("This test failed").toBe(null); | ||
} catch (e) { | ||
expect(e.toString()).toMatch(`Error: Issuer's home domain is missing`); | ||
} | ||
}); | ||
|
||
test("stellar.toml CURRENCIES missing", async () => { | ||
const homeDomain = "example.com"; | ||
axiosMock | ||
.expects("get") | ||
.withArgs(sinon.match(`https://${homeDomain}/.well-known/stellar.toml`)) | ||
.returns( | ||
Promise.resolve({ | ||
data: "", | ||
}), | ||
); | ||
|
||
try { | ||
// @ts-ignore | ||
const res = await getApprovalServerUrl({ | ||
asset_code: "USD", | ||
asset_issuer: | ||
"GDBMMVJKWGT2N6HZ2BGMFHKODASVFYIHL2VS3RUTB3B3QES2R6YFXGQW", | ||
home_domain: homeDomain, | ||
}); | ||
expect("This test failed").toBe(null); | ||
} catch (e) { | ||
expect(e.toString()).toMatch( | ||
`Error: stellar.toml at ${homeDomain} does not contain CURRENCIES` + | ||
` field`, | ||
); | ||
} | ||
}); | ||
|
||
test("stellar.toml approval_server missing", async () => { | ||
const homeDomain = "example.com"; | ||
axiosMock | ||
.expects("get") | ||
.withArgs(sinon.match(`https://${homeDomain}/.well-known/stellar.toml`)) | ||
.returns( | ||
Promise.resolve({ | ||
data: ` | ||
[[CURRENCIES]] | ||
code = "USD" | ||
issuer = "GDBMMVJKWGT2N6HZ2BGMFHKODASVFYIHL2VS3RUTB3B3QES2R6YFXGQW" | ||
`, | ||
}), | ||
); | ||
|
||
try { | ||
// @ts-ignore | ||
const res = await getApprovalServerUrl({ | ||
asset_code: "USD", | ||
asset_issuer: | ||
"GDBMMVJKWGT2N6HZ2BGMFHKODASVFYIHL2VS3RUTB3B3QES2R6YFXGQW", | ||
home_domain: homeDomain, | ||
}); | ||
expect("This test failed").toBe(null); | ||
} catch (e) { | ||
expect(e.toString()).toMatch( | ||
`Error: stellar.toml at ${homeDomain} does not contain` + | ||
` approval_server information for this asset`, | ||
); | ||
} | ||
}); | ||
|
||
test("stellar.toml asset not found", async () => { | ||
const homeDomain = "example.com"; | ||
axiosMock | ||
.expects("get") | ||
.withArgs(sinon.match(`https://${homeDomain}/.well-known/stellar.toml`)) | ||
.returns( | ||
Promise.resolve({ | ||
data: ` | ||
[[CURRENCIES]] | ||
code = "USD" | ||
issuer = "GDBMMVJKWGT2N6HZ2BGMFHKODASVFYIHL2VS3RUTB3B3QES2R6YFXGQW" | ||
`, | ||
}), | ||
); | ||
|
||
try { | ||
// @ts-ignore | ||
const res = await getApprovalServerUrl({ | ||
asset_code: "EUR", | ||
asset_issuer: | ||
"GDBMMVJKWGT2N6HZ2BGMFHKODASVFYIHL2VS3RUTB3B3QES2R6YFXGQW", | ||
home_domain: homeDomain, | ||
}); | ||
expect("This test failed").toBe(null); | ||
} catch (e) { | ||
expect(e.toString()).toMatch( | ||
`Error: CURRENCY EUR:` + | ||
`GDBMMVJKWGT2N6HZ2BGMFHKODASVFYIHL2VS3RUTB3B3QES2R6YFXGQW` + | ||
` not found on stellar.toml at ${homeDomain}`, | ||
); | ||
} | ||
}); | ||
|
||
test("approval server URL is returned", async () => { | ||
const homeDomain = "example.com"; | ||
axiosMock | ||
.expects("get") | ||
.withArgs(sinon.match(`https://${homeDomain}/.well-known/stellar.toml`)) | ||
.returns( | ||
Promise.resolve({ | ||
data: ` | ||
[[CURRENCIES]] | ||
code = "USD" | ||
issuer = "GDBMMVJKWGT2N6HZ2BGMFHKODASVFYIHL2VS3RUTB3B3QES2R6YFXGQW" | ||
approval_server = "https://example.com/approve" | ||
`, | ||
}), | ||
); | ||
|
||
try { | ||
const res = await getApprovalServerUrl({ | ||
asset_code: "USD", | ||
asset_issuer: | ||
"GDBMMVJKWGT2N6HZ2BGMFHKODASVFYIHL2VS3RUTB3B3QES2R6YFXGQW", | ||
home_domain: homeDomain, | ||
}); | ||
expect(res).toEqual("https://example.com/approve"); | ||
} catch (e) { | ||
expect(e).toBe(null); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { StellarTomlResolver } from "stellar-sdk"; | ||
import { RegulatedAssetInfo } from "../types/sep8"; | ||
|
||
export async function getApprovalServerUrl( | ||
param: RegulatedAssetInfo, | ||
opts: StellarTomlResolver.StellarTomlResolveOptions = {}, | ||
): Promise<string> { | ||
if (!param.home_domain) { | ||
throw new Error(`Issuer's home domain is missing`); | ||
} | ||
|
||
const tomlObject = await StellarTomlResolver.resolve(param.home_domain, opts); | ||
if (!tomlObject.CURRENCIES) { | ||
throw new Error( | ||
`stellar.toml at ${param.home_domain} does not contain CURRENCIES field`, | ||
); | ||
} | ||
|
||
for (const ast of tomlObject.CURRENCIES) { | ||
if (ast.code === param.asset_code && ast.issuer === param.asset_issuer) { | ||
if (!ast.approval_server) { | ||
throw new Error( | ||
`stellar.toml at ${ | ||
param.home_domain | ||
} does not contain approval_server information for this asset`, | ||
); | ||
} | ||
|
||
return ast.approval_server; | ||
} | ||
} | ||
|
||
throw new Error( | ||
`CURRENCY ${param.asset_code}:${ | ||
param.asset_issuer | ||
} not found on stellar.toml at ${param.home_domain}`, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters