This repository has been archived by the owner on Dec 12, 2024. It is now read-only.
generated from TBD54566975/tbd-project-template
-
Notifications
You must be signed in to change notification settings - Fork 105
Mock PFI Servers #1223
Merged
Merged
Mock PFI Servers #1223
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
1689248
Wallet: Get Offerings - js/kt
angiejones 00f1853
added mock server and tests for Kotlin
angiejones 78ede77
test data
angiejones 0bb5a2e
JS mock PFI server and tests
angiejones 2bec4a6
Merge branch 'main' into wallet-offerings-kt
angiejones File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
207 changes: 207 additions & 0 deletions
207
site/testsuites/testsuite-kotlin/src/test/kotlin/docs/tbdex/TestData.kt
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,207 @@ | ||
package docs.tbdex | ||
|
||
import com.danubetech.verifiablecredentials.CredentialSubject | ||
import de.fxlae.typeid.TypeId | ||
import foundation.identity.did.Service | ||
import tbdex.sdk.protocol.models.* | ||
import tbdex.sdk.protocol.serialization.Json | ||
import web5.sdk.credentials.VcDataModel | ||
import web5.sdk.credentials.VerifiableCredential | ||
import web5.sdk.credentials.model.ConstraintsV2 | ||
import web5.sdk.credentials.model.FieldV2 | ||
import web5.sdk.credentials.model.InputDescriptorV2 | ||
import web5.sdk.credentials.model.PresentationDefinitionV2 | ||
import web5.sdk.crypto.InMemoryKeyManager | ||
import web5.sdk.dids.Did | ||
import web5.sdk.dids.methods.dht.CreateDidDhtOptions | ||
import web5.sdk.dids.methods.dht.DidDht | ||
import java.net.URI | ||
import java.time.OffsetDateTime | ||
import java.util.* | ||
|
||
object TestData { | ||
const val ALICE = "alice" | ||
const val PFI = "pfi" | ||
private val aliceKeyManager = InMemoryKeyManager() | ||
val ALICE_DID: Did = DidDht.create(aliceKeyManager) | ||
|
||
val serviceToAdd = Service.builder() | ||
.id(URI("pfi")) | ||
.type("PFI") | ||
.serviceEndpoint("http://localhost:9000") | ||
.build() | ||
|
||
val options = CreateDidDhtOptions( | ||
publish = true, | ||
services = listOf(serviceToAdd), | ||
) | ||
|
||
val PFI_DID = DidDht.create(InMemoryKeyManager(), options) | ||
|
||
fun getPresentationDefinition(): PresentationDefinitionV2 { | ||
return buildPresentationDefinition( | ||
inputDescriptors = listOf( | ||
buildInputDescriptor(fields = listOf(buildField(paths = arrayOf("$.credentialSubject.btcAddress")))) | ||
) | ||
) | ||
} | ||
|
||
fun getVC(): VerifiableCredential { | ||
val credentialSubject = CredentialSubject.builder() | ||
.id(URI.create(ALICE_DID.uri)) | ||
.claims(mutableMapOf<String, Any>().apply { this["btcAddress"] = "btcAddress123" }) | ||
.build() | ||
|
||
val vc = VcDataModel.builder() | ||
.id(URI.create(UUID.randomUUID().toString())) | ||
.credentialSubject(credentialSubject) | ||
.issuer(URI.create(ALICE_DID.uri)) | ||
.issuanceDate(Date()) | ||
.build() | ||
|
||
return VerifiableCredential.create("test type", ALICE_DID.uri, ALICE_DID.uri, vc) | ||
} | ||
|
||
fun getOffering(from: String = PFI_DID.uri, requiredClaims: PresentationDefinitionV2 = getPresentationDefinition()) = | ||
Offering.create( | ||
from = from, | ||
OfferingData( | ||
description = "A sample offering", | ||
payoutUnitsPerPayinUnit = "1", | ||
payinCurrency = CurrencyDetails("USD", "0.01", "100.00"), | ||
payoutCurrency = CurrencyDetails("KES"), | ||
payinMethods = listOf( | ||
PaymentMethod( | ||
kind = "BTC_ADDRESS", | ||
requiredPaymentDetails = requiredPaymentDetailsSchema() | ||
) | ||
), | ||
payoutMethods = listOf( | ||
PaymentMethod( | ||
kind = "MOMO", | ||
requiredPaymentDetails = requiredPaymentDetailsSchema() | ||
) | ||
), | ||
requiredClaims = requiredClaims | ||
) | ||
) | ||
|
||
fun getRfq( | ||
offeringId: TypeId = TypeId.generate(ResourceKind.offering.name), | ||
claims: List<String> = emptyList() | ||
) = Rfq.create( | ||
to = PFI_DID.uri, | ||
from = ALICE_DID.uri, | ||
rfqData = RfqData( | ||
offeringId = offeringId, | ||
payinAmount = "10.00", | ||
payinMethod = SelectedPaymentMethod("BTC_ADDRESS", mapOf("address" to "123456")), | ||
payoutMethod = SelectedPaymentMethod( | ||
"MOMO", mapOf( | ||
"phoneNumber" to "+254712345678", | ||
"accountHolderName" to "Alfred Holder" | ||
) | ||
), | ||
claims = claims | ||
) | ||
) | ||
|
||
fun getQuote() = Quote.create( | ||
ALICE_DID.uri, PFI_DID.uri, TypeId.generate(MessageKind.rfq.name), | ||
QuoteData( | ||
expiresAt = OffsetDateTime.now().plusDays(1), | ||
payin = QuoteDetails("AUD", "10.00", "0.01"), | ||
payout = QuoteDetails("BTC", "0.12", "0.02"), | ||
) | ||
) | ||
|
||
fun getClose() = Close.create( | ||
to = ALICE_DID.uri, | ||
from = PFI_DID.uri, | ||
exchangeId = TypeId.generate(MessageKind.rfq.name), | ||
closeData = CloseData("test reason") | ||
) | ||
|
||
fun getOrder() = Order.create( | ||
to = PFI_DID.uri, | ||
from = ALICE_DID.uri, | ||
exchangeId = TypeId.generate(MessageKind.rfq.name) | ||
) | ||
|
||
fun getOrderStatus() = OrderStatus.create( | ||
to = ALICE_DID.uri, | ||
from = PFI_DID.uri, | ||
exchangeId = TypeId.generate(MessageKind.rfq.name), | ||
orderStatusData = OrderStatusData("PENDING") | ||
) | ||
|
||
fun getOrderStatusWithInvalidDid(): OrderStatus { | ||
val os = OrderStatus.create( | ||
"alice", "pfi", TypeId.generate(MessageKind.rfq.name), OrderStatusData("PENDING") | ||
) | ||
|
||
os.sign(ALICE_DID) | ||
return os | ||
} | ||
|
||
private fun buildField(id: String? = null, vararg paths: String): FieldV2 { | ||
return FieldV2(id = id, path = paths.toList()) | ||
} | ||
|
||
private fun buildPresentationDefinition( | ||
id: String = "test-pd-id", | ||
name: String = "simple PD", | ||
purpose: String = "pd for testing", | ||
inputDescriptors: List<InputDescriptorV2> = listOf() | ||
): PresentationDefinitionV2 { | ||
return PresentationDefinitionV2( | ||
id = id, | ||
name = name, | ||
purpose = purpose, | ||
inputDescriptors = inputDescriptors | ||
) | ||
} | ||
|
||
private fun buildInputDescriptor( | ||
id: String = "whatever", | ||
purpose: String = "id for testing", | ||
fields: List<FieldV2> = listOf() | ||
): InputDescriptorV2 { | ||
return InputDescriptorV2( | ||
id = id, | ||
purpose = purpose, | ||
constraints = ConstraintsV2(fields = fields) | ||
) | ||
} | ||
|
||
private fun requiredPaymentDetailsSchema() = Json.jsonMapper.readTree( | ||
""" | ||
{ | ||
"${'$'}schema": "http://json-schema.org/draft-07/schema", | ||
"additionalProperties": false, | ||
"type": "object", | ||
"properties": { | ||
"phoneNumber": { | ||
"minLength": 12, | ||
"pattern": "^+2547[0-9]{8}${'$'}", | ||
"description": "Mobile Money account number of the Recipient", | ||
"type": "string", | ||
"title": "Phone Number", | ||
"maxLength": 12 | ||
}, | ||
"accountHolderName": { | ||
"pattern": "^[A-Za-zs'-]+${'$'}", | ||
"description": "Name of the account holder as it appears on the Mobile Money account", | ||
"type": "string", | ||
"title": "Account Holder Name", | ||
"maxLength": 32 | ||
} | ||
}, | ||
"required": [ | ||
"accountNumber", | ||
"accountHolderName" | ||
] | ||
} | ||
""".trimIndent() | ||
) | ||
} |
84 changes: 43 additions & 41 deletions
84
site/testsuites/testsuite-kotlin/src/test/kotlin/docs/tbdex/wallet/GetOfferingsTest.kt
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 |
---|---|---|
@@ -1,76 +1,78 @@ | ||
|
||
package website.tbd.developer.site.docs.tbdex.wallet | ||
|
||
import foundation.identity.did.Service | ||
import okhttp3.mockwebserver.MockResponse | ||
import okhttp3.mockwebserver.MockWebServer | ||
import tbdex.sdk.httpclient.TbdexHttpClient | ||
import tbdex.sdk.protocol.models.Offering | ||
import web5.sdk.crypto.InMemoryKeyManager | ||
import web5.sdk.dids.methods.dht.CreateDidDhtOptions | ||
import web5.sdk.dids.methods.dht.DidDht | ||
import java.net.URI | ||
import tbdex.sdk.protocol.serialization.Json | ||
import java.net.HttpURLConnection | ||
import docs.tbdex.TestData | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.* | ||
import org.junit.jupiter.api.Assertions.* | ||
|
||
/** | ||
* Tests for Wallet: Get Offerings guide | ||
*/ | ||
class GetOfferingsTest { | ||
|
||
/* | ||
TODO: set PFI DID to one that has offerings. | ||
waiting on the Mock PFI to be updated to include offerings. | ||
*/ | ||
val serviceToAdd = Service.builder() | ||
.id(URI("pfi")) | ||
.type("PFI") | ||
.serviceEndpoint("http://localhost:9000") | ||
.build() | ||
private lateinit var server: MockWebServer | ||
private val pfi = TestData.PFI_DID | ||
private val pfiDid = pfi.uri | ||
|
||
val options = CreateDidDhtOptions( | ||
publish = true, | ||
services = listOf(serviceToAdd), | ||
) | ||
@BeforeEach | ||
fun setup() { | ||
server = MockWebServer() | ||
server.start(9000) // pfiDid resolves to http://localhost:9000 | ||
|
||
val pfi = DidDht.create(InMemoryKeyManager(), options) | ||
val pfiDid = pfi.uri | ||
val offering = TestData.getOffering(pfiDid, TestData.getPresentationDefinition()) | ||
offering.sign(pfi) | ||
val mockOfferings = listOf(offering) | ||
val mockResponseString = Json.jsonMapper.writeValueAsString(mapOf("data" to mockOfferings)) | ||
server.enqueue(MockResponse().setBody(mockResponseString).setResponseCode(HttpURLConnection.HTTP_OK)) | ||
} | ||
|
||
@AfterEach | ||
fun tearDown() { | ||
server.shutdown() | ||
} | ||
|
||
@Test | ||
fun `get all offerings`() { | ||
// :snippet-start: walletGetOfferingsKt | ||
val offerings = TbdexHttpClient.getOfferings(pfiDid) | ||
// :snippet-end: | ||
|
||
//TODO: add tests once the mock PFI is updated to include offerings. | ||
assertNotEquals(0, offerings.size, "No offerings found from PFI") | ||
} | ||
|
||
@Test | ||
fun `find matching offerings`() { | ||
val pfiDids = arrayOf(pfiDid) | ||
|
||
// :snippet-start: walletFindMatchingOfferingsKt | ||
val payinCurrencyCode = "USD"; // Desired payin currency code | ||
val payoutCurrencyCode = "KES"; // Desired payout currency code | ||
|
||
val pfiDids = arrayOf(pfiDid) | ||
|
||
// :snippet-start: walletFindMatchingOfferingsKt | ||
val payinCurrencyCode = "USD"; // Desired payin currency code | ||
val payoutCurrencyCode = "KES"; // Desired payout currency code | ||
val matchedOfferings = ArrayList<Offering>() // Array to store the matched offerings | ||
|
||
val matchedOfferings = ArrayList<Offering>() // Array to store the matched offerings | ||
// Loop through the all PFIs in your network | ||
for (pfiDid in pfiDids) { | ||
|
||
// Loop through the all PFIs in your network | ||
for (pfiDid in pfiDids) { | ||
// Makes a request to the PFI to get their offerings | ||
val offerings = TbdexHttpClient.getOfferings(pfiDid) | ||
|
||
// Makes a request to the PFI to get their offerings | ||
val offerings = TbdexHttpClient.getOfferings(pfiDid) | ||
// Filter offerings based on the currency pair | ||
val filteredOfferings = offerings.filter { offering -> | ||
offering.data.payinCurrency.currencyCode == payinCurrencyCode && | ||
offering.data.payoutCurrency.currencyCode == payoutCurrencyCode | ||
} | ||
|
||
// Filter offerings based on the currency pair | ||
val filteredOfferings = offerings.filter { offering -> | ||
offering.data.payinCurrency.currencyCode == payinCurrencyCode && | ||
offering.data.payoutCurrency.currencyCode == payoutCurrencyCode | ||
matchedOfferings.addAll(filteredOfferings) | ||
} | ||
// :snippet-end: | ||
|
||
matchedOfferings.addAll(filteredOfferings) | ||
} | ||
// :snippet-end: | ||
|
||
//TODO: add tests once the mock PFI is updated to include offerings. | ||
assertNotEquals(0, matchedOfferings.size, "No matching offerings found") | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lot of extra stuff in this file. I just got it working for my 2 tests. we can add/remove stuff as we're building out the other tests