feat: adding docs for payment metadata (#124)

Co-authored-by: vacwmX <vacwm01@gmail.com>
Co-authored-by: ok300 <106775972+ok300@users.noreply.github.com>
This commit is contained in:
yse
2024-02-29 23:32:59 +01:00
committed by GitHub
parent 09265637bf
commit 6254560488
10 changed files with 845 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
using Breez.Sdk;
using System.Text.Json;
public class MetadataSnippets
{
public void SetPaymentMetadata(BlockingBreezServices sdk)
{
// ANCHOR: set-payment-metadata
sdk.SetPaymentMetadata("target-payment-hash", "{\"myCustomValue\":true}");
// ANCHOR_END: set-payment-metadata
}
public void FilterPaymentMetadata(BlockingBreezServices sdk)
{
// ANCHOR: filter-payment-metadata
try
{
var metadataFilters = new List<MetadataFilter>() {
new MetadataFilter(
jsonPath: "myCustomValue",
jsonValue: "true"
)
};
var payments = sdk.ListPayments(
new ListPaymentsRequest(
metadataFilters: metadataFilters
)
);
}
catch (Exception)
{
// Handle error
}
// ANCHOR_END: filter-payment-metadata
}
public void FilterPaymentMetadataString(BlockingBreezServices sdk)
{
// ANCHOR: filter-payment-metadata-string
var metadataFilters = new List<MetadataFilter>() {
new MetadataFilter(
jsonPath: "customerName",
jsonValue: "\"Satoshi Nakamoto\""
),
new MetadataFilter(
jsonPath: "customerName",
jsonValue: JsonSerializer.Serialize("Satoshi Nakamoto")
)
};
// ANCHOR_END: filter-payment-metadata-string
}
public void FilterPaymentMetadataObject(BlockingBreezServices sdk)
{
// ANCHOR: filter-payment-metadata-object
// This will *NOT* work
var _metadataFilters = new List<MetadataFilter>() {
new MetadataFilter(
jsonPath: "parent.nestedArray",
jsonValue: "[1, 2, 3]"
)
};
// Any of these will work
var metadataFilters = new List<MetadataFilter>() {
new MetadataFilter(
jsonPath: "parent.nestedArray",
jsonValue: "[1,2,3]"
),
new MetadataFilter(
jsonPath: "parent.nestedArray",
jsonValue: JsonSerializer.Serialize(new int[] {1, 2, 3})
)
};
// ANCHOR_END: filter-payment-metadata-object
}
}

View File

@@ -0,0 +1,51 @@
import 'package:breez_sdk/breez_sdk.dart';
import 'package:breez_sdk/bridge_generated.dart';
Future<void> setPaymentMetadata({required String paymentHash, required String metadata}) async {
// ANCHOR: set-payment-metadata
await BreezSDK().setPaymentMetadata(hash: "target-payment-hash", metadata: '{"myCustomValue":true}');
// ANCHOR_END: set-payment-metadata
}
Future<void> filterPaymentMetadata() async {
// ANCHOR: filter-payment-metadata
List<MetadataFilter> metadataFilters = [
MetadataFilter(
jsonPath: "myCustomValue",
jsonValue: "true",
),
];
await BreezSDK().listPayments(
req: ListPaymentsRequest(
metadataFilters: metadataFilters
));
// ANCHOR_END: filter-payment-metadata
// ANCHOR: filter-payment-metadata-string
metadataFilters = [
MetadataFilter(
jsonPath: "customerName",
jsonValue: '"Satoshi Nakamoto"',
),
];
// ANCHOR_END: filter-payment-metadata-string
// ANCHOR: filter-payment-metadata-object
// This will *NOT* work
metadataFilters = [
MetadataFilter(
jsonPath: "parent.nestedArray",
jsonValue: "[1, 2, 3]",
),
];
// Any of these will work
metadataFilters = [
MetadataFilter(
jsonPath: "parent.nestedArray",
jsonValue: "[1,2,3]",
),
];
// ANCHOR_END: filter-payment-metadata-object
}

72
snippets/go/metadata.go Normal file
View File

@@ -0,0 +1,72 @@
package example
import (
"encoding/json"
"log"
"github.com/breez/breez-sdk-go/breez_sdk"
)
func SetPaymentMetadata() {
// ANCHOR: set-payment-metadata
sdk.SetPaymentMetadata("target-payment-hash", `{"myCustomValue":true}`)
// ANCHOR_END: set-payment-metadata
}
func FilterPaymentMetadata() {
// ANCHOR: filter-payment-metadata
metadataFilters := []breez_sdk.MetadataFilter{
{JsonPath: "myCustomValue", JsonValue: "true"},
}
payments, err := sdk.ListPayments(breez_sdk.ListPaymentsRequest{
MetadataFilters: &metadataFilters,
})
if err != nil {
// handle error
}
// ANCHOR_END: filter-payment-metadata
log.Printf("%#v", payments)
}
func FilterPaymentMetadataString() {
// ANCHOR: filter-payment-metadata-string
metadataFilters := []breez_sdk.MetadataFilter{
{JsonPath: "customerName", JsonValue: "\"Satoshi Nakamoto\""},
}
jsonValue, _ := json.Marshal("Satoshi Nakamoto")
metadataFilters = []breez_sdk.MetadataFilter{
{
JsonPath: "customerName",
JsonValue: string(jsonValue),
},
}
// ANCHOR_END: filter-payment-metadata-string
sdk.ListPayments(breez_sdk.ListPaymentsRequest{
MetadataFilters: &metadataFilters,
})
}
func FilterPaymentMetadataObject() {
// ANCHOR: filter-payment-metadata-object
// This will *NOT* work
metadataFilters := []breez_sdk.MetadataFilter{
{JsonPath: "parent.nestedArray", JsonValue: "[1, 2, 3]"},
}
// Any of these will work
jsonValue, _ := json.Marshal([]int{1, 2, 3})
metadataFilters = []breez_sdk.MetadataFilter{
{JsonPath: "parent.nestedArray", JsonValue: "[1,2,3]"},
{JsonPath: "parent.nestedArray", JsonValue: string(jsonValue)},
}
// ANCHOR_END: filter-payment-metadata-object
sdk.ListPayments(breez_sdk.ListPaymentsRequest{
MetadataFilters: &metadataFilters,
})
}

View File

@@ -0,0 +1,57 @@
package com.example.kotlinmpplib
import breez_sdk.*
class Metadata {
fun SetPaymentMetadata(sdk: BlockingBreezServices) {
// ANCHOR: set-payment-metadata
try {
sdk.setPaymentMetadata("target-payment-hash", """{"myCustomValue":true}""")
} catch (e: Exception) {
// Handle error
}
// ANCHOR_END: set-payment-metadata
}
fun FilterPaymentMetadata(sdk: BlockingBreezServices) {
// ANCHOR: filter-payment-metadata
val metadataFilters = listOf(MetadataFilter(
jsonPath = "myCustomValue",
jsonValue = "true"
))
try {
sdk.listPayments(
ListPaymentsRequest(
metadataFilters = metadataFilters
))
} catch (e: Exception) {
// handle error
}
// ANCHOR_END: filter-payment-metadata
}
fun FilterPaymentMetadataString(sdk: BlockingBreezServices) {
// ANCHOR: filter-payment-metadata-string
val metadataFilters = listOf(MetadataFilter(
jsonPath = "customerName",
jsonValue = "\"Satoshi Nakamoto\""
))
// ANCHOR_END: filter-payment-metadata-string
}
fun FilterPaymentMetadataObject(sdk: BlockingBreezServices) {
// ANCHOR: filter-payment-metadata-object
// This will *NOT* work
val _metadataFilters = listOf(MetadataFilter(
jsonPath = "parent.nestedArray",
jsonValue = "[1, 2, 3]"
))
// Any of these will work
val metadataFilters = listOf(MetadataFilter(
jsonPath = "parent.nestedArray",
jsonValue = "[1,2,3]"
))
// ANCHOR_END: filter-payment-metadata-object
}
}

View File

@@ -0,0 +1,45 @@
import breez_sdk
def set_payment_metadata(sdk_services):
try:
# ANCHOR: set-payment-metadata
sdk_services.set_payment_metadata("target-payment-hash", '{"myCustomValue":true}')
# ANCHOR_END: set-payment-metadata
except Exception as error:
# handle error
raise
def filter_payment_metadata(sdk_services):
# ANCHOR: filter-payment-metadata
metadata_filters = [
breez_sdk.MetadataFilter("myCustomValue", "true")
]
try:
sdk_services.list_payments(breez_sdk.ListPaymentsRequest(
metadata_filters = metadata_filters
))
except Exception as error:
# handle error
raise
# ANCHOR_END: filter-payment-metadata
# ANCHOR: filter-payment-metadata-string
metadata_filters = [
breez_sdk.MetadataFilter("customerName", "\"Satoshi Nakamoto\""),
breez_sdk.MetadataFilter("customerName", json.dumps("Satoshi Nakamoto")),
]
# ANCHOR_END: filter-payment-metadata-string
# ANCHOR: filter-payment-metadata-object
# This will *NOT* work
metadata_filters = [
breez_sdk.MetadataFilter("parent.nestedArray", "[1, 2, 3]")
]
# Any of these will work
metadata_filters = [
breez_sdk.MetadataFilter("parent.nestedArray", "[1,2,3]"),
breez_sdk.MetadataFilter("parent.nestedArray", json.dumps([1,2,3], separators=(',', ':'))),
]
# ANCHOR_END: filter-payment-metadata-object

View File

@@ -0,0 +1,66 @@
import { setPaymentMetadata, listPayments } from '@breeztech/react-native-breez-sdk'
const testSetPaymentMetadata = async () => {
// ANCHOR: set-payment-metadata
await setPaymentMetadata('target-payment-hash', '{"myCustomValue":true}')
// ANCHOR_END: set-payment-metadata
}
const testFilterPaymentMetadata = async () => {
// ANCHOR: filter-payment-metadata
const metadataFilters = [
{
jsonPath: 'myCustomValue',
jsonValue: 'true'
}
]
try {
await listPayments({
metadataFilters
})
} catch (err) {
// handle error
}
// ANCHOR_END: filter-payment-metadata
}
const testFilterPaymentMetadataString = async () => {
// ANCHOR: filter-payment-metadata-string
// Note: These are equivalent
const metadataFilters = [
{
jsonPath: 'customerName',
jsonValue: 'Satoshi Nakamoto'
},
{
jsonPath: 'customerName',
jsonValue: JSON.stringify('Satoshi Nakamoto')
}
]
// ANCHOR_END: filter-payment-metadata-string
}
const testFilterPaymentMetadataObject = async () => {
// ANCHOR: filter-payment-metadata-object
// This will *NOT* work
const _metadataFilters = [
{
jsonPath: 'parent.nestedArray',
jsonValue: '[1, 2, 3]'
}
]
// Any of these will work
const metadataFilters = [
{
jsonPath: 'parent.nestedArray',
jsonValue: '[1,2,3]'
},
{
jsonPath: 'parent.nestedArray',
jsonValue: JSON.stringify([1, 2, 3])
}
]
// ANCHOR_END: filter-payment-metadata-object
}

View File

@@ -0,0 +1,73 @@
use std::sync::Arc;
use anyhow::Result;
use breez_sdk_core::*;
async fn set_payment_metadata(sdk: Arc<BreezServices>) -> Result<()> {
// ANCHOR: set-payment-metadata
sdk.set_payment_metadata("target-payment-hash", r#"{"myCustomValue":true}"#).await?;
// ANCHOR_END: set-payment-metadata
Ok(())
}
async fn filter_payment_metadata(sdk: Arc<BreezServices>) -> Result<()> {
// ANCHOR: filter-payment-metadata
let metadata_filters = vec![
MetadataFilter {
json_path: "myCustomValue".to_string(),
json_value: "true".to_string(),
},
];
sdk.list_payments(ListPaymentsRequest {
metadata_filters,
..Default::default(),
}).await?;
// ANCHOR_END: filter-payment-metadata
}
async fn filter_payment_metadata_string(sdk: Arc<BreezServices>) -> Result<()> {
// ANCHOR: filter-payment-metadata-string
// Note: The following are equivalent
let metadata_filters = vec![
MetadataFilter {
json_path: "customerName".to_string(),
json_value: r#""Satoshi Nakamoto""#.to_string(),
},
MetadataFilter {
json_path: "customerName".to_string(),
json_value: serde_json::json!("Satoshi Nakamoto").to_string(),
},
];
// ANCHOR_END: filter-payment-metadata-string
}
async fn filter_payment_metadata_object(sdk: Arc<BreezServices>) -> Result<()> {
// ANCHOR: filter-payment-metadata-object
// This will *NOT* work
let metadata_filters = vec![
MetadataFilter {
json_path: "parent.nestedArray".to_string(),
json_value: r#"[1, 2, 3]"#.to_string(),
},
];
// Any of these will work
let metadata_filters = vec![
MetadataFilter {
json_path: "parent.nestedArray".to_string(),
json_value: r#"[1,2,3]"#.to_string(),
},
];
// ANCHOR_END: filter-payment-metadata-object
// ANCHOR: filter-payment-metadata-object-serde
let metadata_filters = vec![
MetadataFilter {
json_path: "parent.nestedArray".to_string(),
json_value: serde_json::json!(&[1, 2, 3]).to_string(),
},
];
// ANCHOR_END: filter-payment-metadata-object-serde
Ok(())
}

View File

@@ -0,0 +1,76 @@
//
// Metadata.swift
//
//
//
import Foundation
import BreezSDK
func SetPaymentMetadata(sdk: BlockingBreezServices) throws {
// ANCHOR: set-payment-metadata
try sdk.setPaymentMetadata(hash: "target-payment-hash", metadata: #"{"myCustomValue":true}"#)
// ANCHOR_END: set-payment-metadata
}
func FilterPaymentMetadata(sdk: BlockingBreezServices) -> [Payment]? {
// ANCHOR: filter-payment-metadata
let metadataFilters = [
MetadataFilter(
jsonPath: "myCustomValue",
jsonValue: "true"
)
]
let payments = try? sdk.listPayments(
req: ListPaymentsRequest(
metadataFilters: metadataFilters
)
)
// ANCHOR_END: filter-payment-metadata
return payments
}
func FilterPaymentMetadataString(sdk: BlockingBreezServices) -> [Payment]? {
// ANCHOR: filter-payment-metadata-string
let metadataFilters = [
MetadataFilter(
jsonPath: "myCustomValue",
jsonValue: #""true""#
)
]
// ANCHOR_END: filter-payment-metadata-string
return try? sdk.listPayments(
req: ListPaymentsRequest(
metadataFilters: metadataFilters
)
)
}
func FilterPaymentMetadataObject(sdk: BlockingBreezServices) -> [Payment]? {
// ANCHOR: filter-payment-metadata-object
// This will *NOT* work
var metadataFilters = [
MetadataFilter(
jsonPath: "myCustomValue",
jsonValue: #"[1, 2, 3]"#
)
]
// Any of these will work
metadataFilters = [
MetadataFilter(
jsonPath: "myCustomValue",
jsonValue: #"[1,2,3]"#
)
]
// ANCHOR_END: filter-payment-metadata-object
return try? sdk.listPayments(
req: ListPaymentsRequest(
metadataFilters: metadataFilters
)
)
}

View File

@@ -12,6 +12,7 @@
- [Receiving payments via mobile notifications](guide/payment_notification.md) - [Receiving payments via mobile notifications](guide/payment_notification.md)
- [iOS](guide/ios_notification_service_extension.md) - [iOS](guide/ios_notification_service_extension.md)
- [Android](guide/android_notification_foreground_service.md) - [Android](guide/android_notification_foreground_service.md)
- [Adding and filtering for payment metadata](guide/payment_metadata.md)
- [Connecting to an LSP](guide/connecting_lsp.md) - [Connecting to an LSP](guide/connecting_lsp.md)
- [Receiving an On-Chain Transaction](guide/receive_onchain.md) - [Receiving an On-Chain Transaction](guide/receive_onchain.md)
- [Sending an On-Chain Transaction](guide/send_onchain.md) - [Sending an On-Chain Transaction](guide/send_onchain.md)

View File

@@ -0,0 +1,326 @@
# Adding and filtering for payment metadata
## Usage
As developers, we understand the necessity to associate external metadata to a certain payment. The Breez SDK allows you to easily do so with the `set_payment_metadata` method:
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
{{#include ../../snippets/rust/src/metadata.rs:set-payment-metadata}}
```
</section>
<div slot="title">Swift</div>
<section>
```swift,ignore
{{#include ../../snippets/swift/BreezSDKExamples/Sources/Metadata.swift:set-payment-metadata}}
```
</section>
<div slot="title">Kotlin</div>
<section>
```kotlin,ignore
{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Metadata.kt:set-payment-metadata}}
```
</section>
<div slot="title">React Native</div>
<section>
```typescript
{{#include ../../snippets/react-native/metadata.ts:set-payment-metadata}}
```
</section>
<div slot="title">Dart</div>
<section>
```dart,ignore
{{#include ../../snippets/dart_snippets/lib/metadata.dart:set-payment-metadata}}
```
</section>
<div slot="title">Python</div>
<section>
```python,ignore
{{#include ../../snippets/python/src/metadata.py:set-payment-metadata}}
```
</section>
<div slot="title">Go</div>
<section>
```go,ignore
{{#include ../../snippets/go/metadata.go:set-payment-metadata}}
```
</section>
<div slot="title">C#</div>
<section>
```cs,ignore
{{#include ../../snippets/csharp/Metadata.cs:set-payment-metadata}}
```
</section>
</custom-tabs>
Once the metadata has been set, you can filter for the specified value using the `list_payments` method:
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
{{#include ../../snippets/rust/src/metadata.rs:filter-payment-metadata}}
```
</section>
<div slot="title">Swift</div>
<section>
```swift,ignore
{{#include ../../snippets/swift/BreezSDKExamples/Sources/Metadata.swift:filter-payment-metadata}}
```
</section>
<div slot="title">Kotlin</div>
<section>
```kotlin,ignore
{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Metadata.kt:filter-payment-metadata}}
```
</section>
<div slot="title">React Native</div>
<section>
```typescript
{{#include ../../snippets/react-native/metadata.ts:filter-payment-metadata}}
```
</section>
<div slot="title">Dart</div>
<section>
```dart,ignore
{{#include ../../snippets/dart_snippets/lib/metadata.dart:filter-payment-metadata}}
```
</section>
<div slot="title">Python</div>
<section>
```python,ignore
{{#include ../../snippets/python/src/metadata.py:filter-payment-metadata}}
```
</section>
<div slot="title">Go</div>
<section>
```go,ignore
{{#include ../../snippets/go/metadata.go:filter-payment-metadata}}
```
</section>
<div slot="title">C#</div>
<section>
```cs,ignore
{{#include ../../snippets/csharp/Metadata.cs:filter-payment-metadata}}
```
</section>
</custom-tabs>
## Caveats
Searching for metadata is flexible, allowing you to search and compare all JSON-supported types (nested ones too, using [JSONPath](https://www.ibm.com/docs/en/netezza?topic=ddt-jsonpath)), but with a couple of caveats:
### 2.1 Filtering for Strings
Since the filter works as a one-to-one comparison to the JSON value, strings **must** be wrapped in double-quotes in order to be properly filtered:
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
{{#include ../../snippets/rust/src/metadata.rs:filter-payment-metadata-string}}
```
</section>
<div slot="title">Swift</div>
<section>
```swift,ignore
{{#include ../../snippets/swift/BreezSDKExamples/Sources/Metadata.swift:filter-payment-metadata-string}}
```
</section>
<div slot="title">Kotlin</div>
<section>
```kotlin,ignore
{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Metadata.kt:filter-payment-metadata-string}}
```
</section>
<div slot="title">React Native</div>
<section>
```typescript
{{#include ../../snippets/react-native/metadata.ts:filter-payment-metadata-string}}
```
</section>
<div slot="title">Dart</div>
<section>
```dart,ignore
{{#include ../../snippets/dart_snippets/lib/metadata.dart:filter-payment-metadata-string}}
```
</section>
<div slot="title">Python</div>
<section>
```python,ignore
{{#include ../../snippets/python/src/metadata.py:filter-payment-metadata-string}}
```
</section>
<div slot="title">Go</div>
<section>
```go,ignore
{{#include ../../snippets/go/metadata.go:filter-payment-metadata-string}}
```
</section>
<div slot="title">C#</div>
<section>
```cs,ignore
{{#include ../../snippets/csharp/Metadata.cs:filter-payment-metadata-string}}
```
</section>
</custom-tabs>
### 2.2 Filtering for Objects/Arrays
You can also compare complex objects against one another, but be careful of whitespaces! Since those are stripped during insertion, passing non-stripped filters will result in improper matching. For example, given the following metadata:
<section>
<pre>
{
"isNested": true,
"parent": {
"nestedArray": [1, 2, 3]
}
}
</pre>
</section>
You would filter for payments matching the nested array as follows:
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
{{#include ../../snippets/rust/src/metadata.rs:filter-payment-metadata-object}}
```
In Rust's case, this check can easily be overcome by using the [serde_json](https://docs.rs/serde_json/latest/serde_json/) crate (which you probably should be using anyway to serialize and insert the metadata):
```rust,ignore
{{#include ../../snippets/rust/src/metadata.rs:filter-payment-metadata-object-serde}}
```
</section>
<div slot="title">Swift</div>
<section>
```swift,ignore
{{#include ../../snippets/swift/BreezSDKExamples/Sources/Metadata.swift:filter-payment-metadata-object}}
```
</section>
<div slot="title">Kotlin</div>
<section>
```kotlin,ignore
{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Metadata.kt:filter-payment-metadata-object}}
```
</section>
<div slot="title">React Native</div>
<section>
```typescript
{{#include ../../snippets/react-native/metadata.ts:filter-payment-metadata-object}}
```
</section>
<div slot="title">Dart</div>
<section>
```dart,ignore
{{#include ../../snippets/dart_snippets/lib/metadata.dart:filter-payment-metadata-object}}
```
</section>
<div slot="title">Python</div>
<section>
```python,ignore
{{#include ../../snippets/python/src/metadata.py:filter-payment-metadata-object}}
```
</section>
<div slot="title">Go</div>
<section>
```go,ignore
{{#include ../../snippets/go/metadata.go:filter-payment-metadata-object}}
```
</section>
<div slot="title">C#</div>
<section>
```cs,ignore
{{#include ../../snippets/csharp/Metadata.cs:filter-payment-metadata-object}}
```
</section>
</custom-tabs>
### 2.3 Same-key Insertion
In case the same key were to be specified twice during insertion, the _last_ one occurring in the string is taken as valid by default. E.g.
<section>
<pre>
{
"completed": true,
"completed": false
}
</pre>
</section>
will insert the value as `false`.
### 2.4 Size Limits
Currently, the SDK limits metadata storage per payment to 1,000 UTF-8 encoded characters, and any insertion beyond that will fail.